From 0cf8f8d0ec9a773abf624313f83e8b1ed3260703 Mon Sep 17 00:00:00 2001 From: David Sodman Date: Wed, 20 Dec 2017 18:19:45 -0800 Subject: SF: Fix mBuffer management Fix logic in synchronization of layer buffer between FE and BE Test: Compile/Run Change-Id: I5b8eeafeba004c1a240e801a2a92a21b8d40d8fe --- services/surfaceflinger/Layer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 78dd40b32f..0299270ef9 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1440,7 +1440,7 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mMatrix[1][0] = ds.active.transform[1][0]; info.mMatrix[1][1] = ds.active.transform[1][1]; { - sp buffer = getBE().compositionInfo.mBuffer; + sp buffer = mActiveBuffer; if (buffer != 0) { info.mActiveBufferWidth = buffer->getWidth(); info.mActiveBufferHeight = buffer->getHeight(); -- cgit v1.2.3-59-g8ed1b From 7124ad30da0a161e8886b4593df7e59679d5e2a0 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Wed, 21 Feb 2018 13:02:45 -0800 Subject: Implement Display Layer Stats Try to collect data for analyzing how many display controller layers we need and what we use them for. Also part of a bug fixing for potential memory leak of existing layer tracing work of winscope. Test: adb shell dumpsys SurfaceFlinger --enable-layer-stats Test: adb shell dumpsys SurfaceFlinger --disable-layer-stats Test: adb shell dumpsys SurfaceFlinger --clear-layer-stats Test: adb shell dumpsys SurfaceFlinger --dump-layer-stats Bug: b/73668062 Bug: b/74071380 Change-Id: Ie08aa85d34db2c2c767b8e27eb5aad6f7c3fb975 --- services/surfaceflinger/Android.bp | 1 + services/surfaceflinger/Layer.cpp | 16 ++ services/surfaceflinger/Layer.h | 2 + services/surfaceflinger/LayerBE.h | 4 +- services/surfaceflinger/LayerProtoHelper.cpp | 7 + services/surfaceflinger/LayerProtoHelper.h | 3 +- services/surfaceflinger/LayerStats.cpp | 182 +++++++++++++++++++++ services/surfaceflinger/LayerStats.h | 68 ++++++++ services/surfaceflinger/SurfaceFlinger.cpp | 67 ++++++++ services/surfaceflinger/SurfaceFlinger.h | 4 + .../surfaceflinger/layerproto/LayerProtoParser.cpp | 30 ++++ .../include/layerproto/LayerProtoParser.h | 22 +++ services/surfaceflinger/layerproto/layers.proto | 16 +- 13 files changed, 419 insertions(+), 3 deletions(-) create mode 100644 services/surfaceflinger/LayerStats.cpp create mode 100644 services/surfaceflinger/LayerStats.h (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 3531c4ebd9..5d68696bf8 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -101,6 +101,7 @@ filegroup { "Layer.cpp", "LayerProtoHelper.cpp", "LayerRejecter.cpp", + "LayerStats.cpp", "LayerVector.cpp", "MessageQueue.cpp", "MonitoredProducer.cpp", diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 0299270ef9..610423047b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -639,6 +639,7 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z hwcInfo.forceClientComposition = true; } else { auto transform = static_cast(orientation); + hwcInfo.transform = transform; auto error = hwcLayer->setTransform(transform); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set transform %s: " @@ -1915,6 +1916,21 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) layerInfo->set_refresh_pending(isBufferLatched()); } +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(hwcInfo.transform); + layerInfo->set_hwc_transform(transform); +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index b203a7b57b..9c4f1cee1e 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -290,6 +290,8 @@ public: void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing); + void writeToProto(LayerProto* layerInfo, int32_t hwcId); + protected: /* * onDraw - draws the surface. diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 5965f23bd9..d0cc8e7419 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -70,7 +70,8 @@ public: layer(nullptr), forceClientComposition(false), compositionType(HWC2::Composition::Invalid), - clearClientTarget(false) {} + clearClientTarget(false), + transform(HWC2::Transform::None) {} HWComposer* hwc; HWC2::Layer* layer; @@ -80,6 +81,7 @@ public: Rect displayFrame; FloatRect sourceCrop; HWComposerBufferCache bufferCache; + HWC2::Transform transform; }; diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index 6a33148d27..cc3955087a 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -37,6 +37,13 @@ void LayerProtoHelper::writeToProto(const Rect& rect, RectProto* rectProto) { rectProto->set_right(rect.right); } +void LayerProtoHelper::writeToProto(const FloatRect& rect, FloatRectProto* rectProto) { + rectProto->set_left(rect.left); + rectProto->set_top(rect.top); + rectProto->set_bottom(rect.bottom); + rectProto->set_right(rect.right); +} + void LayerProtoHelper::writeToProto(const half4 color, ColorProto* colorProto) { colorProto->set_r(color.r); colorProto->set_g(color.g); diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h index 45a0b5d173..860da63ed2 100644 --- a/services/surfaceflinger/LayerProtoHelper.h +++ b/services/surfaceflinger/LayerProtoHelper.h @@ -29,6 +29,7 @@ namespace surfaceflinger { class LayerProtoHelper { public: static void writeToProto(const Rect& rect, RectProto* rectProto); + static void writeToProto(const FloatRect& rect, FloatRectProto* rectProto); static void writeToProto(const Region& region, RegionProto* regionProto); static void writeToProto(const half4 color, ColorProto* colorProto); static void writeToProto(const Transform& transform, TransformProto* transformProto); @@ -36,4 +37,4 @@ public: }; } // namespace surfaceflinger -} // namespace android \ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/LayerStats.cpp b/services/surfaceflinger/LayerStats.cpp new file mode 100644 index 0000000000..ea2542c173 --- /dev/null +++ b/services/surfaceflinger/LayerStats.cpp @@ -0,0 +1,182 @@ +/* + * Copyright 2018 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. + */ +#undef LOG_TAG +#define LOG_TAG "LayerStats" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "LayerStats.h" +#include "DisplayHardware/HWComposer.h" + +#include +#include +#include +#include + +namespace android { + +void LayerStats::enable() { + ATRACE_CALL(); + std::lock_guard lock(mMutex); + if (mEnabled) return; + mLayerStatsMap.clear(); + mEnabled = true; + ALOGD("Logging enabled"); +} + +void LayerStats::disable() { + ATRACE_CALL(); + std::lock_guard lock(mMutex); + if (!mEnabled) return; + mEnabled = false; + ALOGD("Logging disabled"); +} + +void LayerStats::clear() { + ATRACE_CALL(); + std::lock_guard lock(mMutex); + mLayerStatsMap.clear(); + ALOGD("Cleared current layer stats"); +} + +bool LayerStats::isEnabled() { + return mEnabled; +} + +void LayerStats::traverseLayerTreeStatsLocked( + const std::vector& layerTree, + const LayerProtoParser::LayerGlobal* layerGlobal) { + for (auto layer : layerTree) { + if (!layer) continue; + traverseLayerTreeStatsLocked(layer->children, layerGlobal); + std::string key = + base::StringPrintf("%s,%s,%s,%s,%s,%s,%s,%s,%s", + destinationLocation(layer->hwcFrame.left, + layerGlobal->resolution[0], true), + destinationLocation(layer->hwcFrame.top, + layerGlobal->resolution[1], false), + destinationSize(layer->hwcFrame.right - layer->hwcFrame.left, + layerGlobal->resolution[0], true), + destinationSize(layer->hwcFrame.bottom - layer->hwcFrame.top, + layerGlobal->resolution[1], false), + layer->type.c_str(), scaleRatioWH(layer).c_str(), + layerTransform(layer->hwcTransform), layer->pixelFormat.c_str(), + layer->dataspace.c_str()); + mLayerStatsMap[key]++; + } +} + +void LayerStats::logLayerStats(const LayersProto& layersProto) { + ATRACE_CALL(); + auto layerGlobal = LayerProtoParser::generateLayerGlobalInfo(layersProto); + auto layerTree = LayerProtoParser::generateLayerTree(layersProto); + std::lock_guard lock(mMutex); + traverseLayerTreeStatsLocked(layerTree, &layerGlobal); + LayerProtoParser::destroyLayerTree(layerTree); +} + +void LayerStats::dump(String8& result) { + ATRACE_CALL(); + ALOGD("Dumping"); + result.append("Count,DstPosX,DstPosY,DstWidth,DstHeight,LayerType,WScale,HScale,"); + result.append("Transform,PixelFormat,Dataspace\n"); + std::lock_guard lock(mMutex); + for (auto& u : mLayerStatsMap) { + result.appendFormat("%u,%s\n", u.second, u.first.c_str()); + } +} + +const char* LayerStats::destinationLocation(int32_t location, int32_t range, bool isHorizontal) { + static const char* locationArray[8] = {"0", "1/8", "1/4", "3/8", "1/2", "5/8", "3/4", "7/8"}; + int32_t ratio = location * 8 / range; + if (ratio < 0) return "N/A"; + if (isHorizontal) { + // X location is divided into 4 buckets {"0", "1/4", "1/2", "3/4"} + if (ratio > 6) return "3/4"; + // use index 0, 2, 4, 6 + return locationArray[ratio & ~1]; + } + if (ratio > 7) return "7/8"; + return locationArray[ratio]; +} + +const char* LayerStats::destinationSize(int32_t size, int32_t range, bool isWidth) { + static const char* sizeArray[8] = {"1/8", "1/4", "3/8", "1/2", "5/8", "3/4", "7/8", "1"}; + int32_t ratio = size * 8 / range; + if (ratio < 0) return "N/A"; + if (isWidth) { + // width is divided into 4 buckets {"1/4", "1/2", "3/4", "1"} + if (ratio > 6) return "1"; + // use index 1, 3, 5, 7 + return sizeArray[ratio | 1]; + } + if (ratio > 7) return "1"; + return sizeArray[ratio]; +} + +const char* LayerStats::layerTransform(int32_t transform) { + return getTransformName(static_cast(transform)); +} + +std::string LayerStats::scaleRatioWH(const LayerProtoParser::Layer* layer) { + if (!layer->type.compare("ColorLayer")) return "N/A,N/A"; + std::string ret = ""; + if (isRotated(layer->hwcTransform)) { + ret += scaleRatio(layer->hwcFrame.right - layer->hwcFrame.left, + static_cast(layer->hwcCrop.bottom - layer->hwcCrop.top)); + ret += ","; + ret += scaleRatio(layer->hwcFrame.bottom - layer->hwcFrame.top, + static_cast(layer->hwcCrop.right - layer->hwcCrop.left)); + } else { + ret += scaleRatio(layer->hwcFrame.right - layer->hwcFrame.left, + static_cast(layer->hwcCrop.right - layer->hwcCrop.left)); + ret += ","; + ret += scaleRatio(layer->hwcFrame.bottom - layer->hwcFrame.top, + static_cast(layer->hwcCrop.bottom - layer->hwcCrop.top)); + } + return ret; +} + +const char* LayerStats::scaleRatio(int32_t destinationScale, int32_t sourceScale) { + // Make scale buckets from <1/64 to >= 16, to avoid floating point + // calculation, x64 on destinationScale first + int32_t scale = destinationScale * 64 / sourceScale; + if (!scale) return "<1/64"; + if (scale < 2) return "1/64"; + if (scale < 4) return "1/32"; + if (scale < 8) return "1/16"; + if (scale < 16) return "1/8"; + if (scale < 32) return "1/4"; + if (scale < 64) return "1/2"; + if (scale < 128) return "1"; + if (scale < 256) return "2"; + if (scale < 512) return "4"; + if (scale < 1024) return "8"; + return ">=16"; +} + +bool LayerStats::isRotated(int32_t transform) { + return transform & HWC_TRANSFORM_ROT_90; +} + +bool LayerStats::isVFlipped(int32_t transform) { + return transform & HWC_TRANSFORM_FLIP_V; +} + +bool LayerStats::isHFlipped(int32_t transform) { + return transform & HWC_TRANSFORM_FLIP_H; +} + +} // namespace android diff --git a/services/surfaceflinger/LayerStats.h b/services/surfaceflinger/LayerStats.h new file mode 100644 index 0000000000..1924110616 --- /dev/null +++ b/services/surfaceflinger/LayerStats.h @@ -0,0 +1,68 @@ +/* + * Copyright 2018 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 +#include +#include +#include + +using namespace android::surfaceflinger; + +namespace android { +class String8; + +class LayerStats { +public: + void enable(); + void disable(); + void clear(); + bool isEnabled(); + void logLayerStats(const LayersProto& layersProto); + void dump(String8& result); + +private: + // Traverse layer tree to get all visible layers' stats + void traverseLayerTreeStatsLocked(const std::vector& layerTree, + const LayerProtoParser::LayerGlobal* layerGlobal); + // Convert layer's top-left position into 8x8 percentage of the display + static const char* destinationLocation(int32_t location, int32_t range, bool isHorizontal); + // Convert layer's size into 8x8 percentage of the display + static const char* destinationSize(int32_t size, int32_t range, bool isWidth); + // Return the name of the transform + static const char* layerTransform(int32_t transform); + // Calculate scale ratios of layer's width/height with rotation information + static std::string scaleRatioWH(const LayerProtoParser::Layer* layer); + // Calculate scale ratio from source to destination and convert to string + static const char* scaleRatio(int32_t destinationScale, int32_t sourceScale); + // Return whether the original buffer is rotated in final composition + static bool isRotated(int32_t transform); + // Return whether the original buffer is V-flipped in final composition + static bool isVFlipped(int32_t transform); + // Return whether the original buffer is H-flipped in final composition + static bool isHFlipped(int32_t transform); + + bool mEnabled = false; + // Protect mLayersStatsMap + std::mutex mMutex; + // Hashmap for tracking the layer stats + // KEY is a concatenation of a particular set of layer properties + // VALUE is the number of times this particular get scanned out + std::unordered_map mLayerStatsMap; +}; + +} // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cb410a14e1..29c1ee23ee 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1449,6 +1449,7 @@ void SurfaceFlinger::handleMessageRefresh() { setUpHWComposer(); doDebugFlashRegions(); doTracing("handleRefresh"); + logLayerStats(); doComposition(); postComposition(refreshStartTime); @@ -1518,6 +1519,25 @@ void SurfaceFlinger::doTracing(const char* where) { } } +void SurfaceFlinger::logLayerStats() { + ATRACE_CALL(); + if (CC_UNLIKELY(mLayerStats.isEnabled())) { + int32_t hwcId = -1; + for (size_t dpy = 0; dpy < mDisplays.size(); ++dpy) { + const sp& displayDevice(mDisplays[dpy]); + if (displayDevice->isPrimary()) { + hwcId = displayDevice->getHwcDisplayId(); + break; + } + } + if (hwcId < 0) { + ALOGE("LayerStats: Hmmm, no primary display?"); + return; + } + mLayerStats.logLayerStats(dumpVisibleLayersProtoInfo(hwcId)); + } +} + void SurfaceFlinger::preComposition(nsecs_t refreshStartTime) { ATRACE_CALL(); @@ -3695,6 +3715,34 @@ status_t SurfaceFlinger::doDump(int fd, const Vector& args, bool asPro dumpWideColorInfo(result); dumpAll = false; } + + if ((index < numArgs) && + (args[index] == String16("--enable-layer-stats"))) { + index++; + mLayerStats.enable(); + dumpAll = false; + } + + if ((index < numArgs) && + (args[index] == String16("--disable-layer-stats"))) { + index++; + mLayerStats.disable(); + dumpAll = false; + } + + if ((index < numArgs) && + (args[index] == String16("--clear-layer-stats"))) { + index++; + mLayerStats.clear(); + dumpAll = false; + } + + if ((index < numArgs) && + (args[index] == String16("--dump-layer-stats"))) { + index++; + mLayerStats.dump(result); + dumpAll = false; + } } if (dumpAll) { @@ -3902,6 +3950,25 @@ LayersProto SurfaceFlinger::dumpProtoInfo(LayerVector::StateSet stateSet) const return layersProto; } +LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(int32_t hwcId) const { + LayersProto layersProto; + + const sp& displayDevice(mDisplays[hwcId]); + SizeProto* resolution = layersProto.mutable_resolution(); + resolution->set_w(displayDevice->getWidth()); + resolution->set_h(displayDevice->getHeight()); + + mDrawingState.traverseInZOrder([&](Layer* layer) { + if (!layer->visibleRegion.isEmpty() && + layer->getBE().mHwcLayers.count(hwcId)) { + LayerProto* layerProto = layersProto.add_layers(); + layer->writeToProto(layerProto, hwcId); + } + }); + + return layersProto; +} + void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, String8& result) const { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index bebd6a5f03..d6aa142168 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -56,6 +56,7 @@ #include "DisplayDevice.h" #include "DispSync.h" #include "FrameTracker.h" +#include "LayerStats.h" #include "LayerVector.h" #include "MessageQueue.h" #include "SurfaceInterceptor.h" @@ -631,6 +632,7 @@ private: void doComposition(); void doDebugFlashRegions(); void doTracing(const char* where); + void logLayerStats(); void doDisplayComposition(const sp& displayDevice, const Region& dirtyRegion); // compose surfaces for display hw. this fails if using GL and the surface @@ -693,6 +695,7 @@ private: void dumpBufferingStats(String8& result) const; void dumpWideColorInfo(String8& result) const; LayersProto dumpProtoInfo(LayerVector::StateSet stateSet) const; + LayersProto dumpVisibleLayersProtoInfo(int32_t hwcId) const; bool isLayerTripleBufferingDisabled() const { return this->mLayerTripleBufferingDisabled; @@ -777,6 +780,7 @@ private: bool mPropagateBackpressure = true; SurfaceInterceptor mInterceptor; SurfaceTracing mTracing; + LayerStats mLayerStats; bool mUseHwcVirtualDisplays = false; // Restrict layers to use two buffers in their bufferqueues. diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index bf37e1e156..7483abde45 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -38,6 +38,19 @@ bool sortLayers(const LayerProtoParser::Layer* lhs, const LayerProtoParser::Laye return lhs->id < rhs->id; } +const LayerProtoParser::LayerGlobal LayerProtoParser::generateLayerGlobalInfo( + const LayersProto& layersProto) { + return {{layersProto.resolution().w(), layersProto.resolution().h()}}; +} + +void LayerProtoParser::destroyLayerTree( + const std::vector& layerTree) { + for (auto layer : layerTree) { + destroyLayerTree(layer->children); + delete layer; + } +} + std::vector LayerProtoParser::generateLayerTree( const LayersProto& layersProto) { auto layerMap = generateMap(layersProto); @@ -102,6 +115,9 @@ LayerProtoParser::Layer* LayerProtoParser::generateLayer(const LayerProto& layer layer->activeBuffer = generateActiveBuffer(layerProto.active_buffer()); layer->queuedFrames = layerProto.queued_frames(); layer->refreshPending = layerProto.refresh_pending(); + layer->hwcFrame = generateRect(layerProto.hwc_frame()); + layer->hwcCrop = generateFloatRect(layerProto.hwc_crop()); + layer->hwcTransform = layerProto.hwc_transform(); return layer; } @@ -127,6 +143,16 @@ LayerProtoParser::Rect LayerProtoParser::generateRect(const RectProto& rectProto return rect; } +LayerProtoParser::FloatRect LayerProtoParser::generateFloatRect(const FloatRectProto& rectProto) { + LayerProtoParser::FloatRect rect; + rect.left = rectProto.left(); + rect.top = rectProto.top(); + rect.right = rectProto.right(); + rect.bottom = rectProto.bottom(); + + return rect; +} + LayerProtoParser::Transform LayerProtoParser::generateTransform( const TransformProto& transformProto) { LayerProtoParser::Transform transform; @@ -242,6 +268,10 @@ std::string LayerProtoParser::Rect::to_string() const { return StringPrintf("[%3d, %3d, %3d, %3d]", left, top, right, bottom); } +std::string LayerProtoParser::FloatRect::to_string() const { + return StringPrintf("[%.2f, %.2f, %.2f, %.2f]", left, top, right, bottom); +} + std::string LayerProtoParser::Region::to_string(const char* what) const { std::string result = StringPrintf(" Region %s (this=%lx count=%d)\n", what, static_cast(id), diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index 78c6cd1345..474727567c 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#pragma once #include @@ -56,6 +57,16 @@ public: std::string to_string() const; }; + class FloatRect { + public: + float left; + float top; + float right; + float bottom; + + std::string to_string() const; + }; + class Region { public: uint64_t id; @@ -95,11 +106,21 @@ public: LayerProtoParser::ActiveBuffer activeBuffer; int32_t queuedFrames; bool refreshPending; + LayerProtoParser::Rect hwcFrame; + LayerProtoParser::FloatRect hwcCrop; + int32_t hwcTransform; std::string to_string() const; }; + class LayerGlobal { + public: + int2 resolution; + }; + + static const LayerGlobal generateLayerGlobalInfo(const LayersProto& layersProto); static std::vector generateLayerTree(const LayersProto& layersProto); + static void destroyLayerTree(const std::vector& layerTree); static std::string layersToString(const std::vector layers); private: @@ -107,6 +128,7 @@ private: static LayerProtoParser::Layer* generateLayer(const LayerProto& layerProto); static LayerProtoParser::Region generateRegion(const RegionProto& regionProto); static LayerProtoParser::Rect generateRect(const RectProto& rectProto); + static LayerProtoParser::FloatRect generateFloatRect(const FloatRectProto& rectProto); static LayerProtoParser::Transform generateTransform(const TransformProto& transformProto); static LayerProtoParser::ActiveBuffer generateActiveBuffer( const ActiveBufferProto& activeBufferProto); diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index d27dc9b2ea..e232f055fc 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -7,6 +7,7 @@ package android.surfaceflinger; // Contains a list of all layers. message LayersProto { repeated LayerProto layers = 1; + optional SizeProto resolution = 2; } // Information about each layer. @@ -64,6 +65,12 @@ message LayerProto { // The number of frames available. optional int32 queued_frames = 28; optional bool refresh_pending = 29; + // The layer's composer backend destination frame + optional RectProto hwc_frame = 30; + // The layer's composer backend source crop + optional FloatRectProto hwc_crop = 31; + // The layer's composer backend transform + optional int32 hwc_transform = 32; } message PositionProto { @@ -95,6 +102,13 @@ message RectProto { optional int32 bottom = 4; } +message FloatRectProto { + optional float left = 1; + optional float top = 2; + optional float right = 3; + optional float bottom = 4; +} + message ActiveBufferProto { optional uint32 width = 1; optional uint32 height = 2; @@ -107,4 +121,4 @@ message ColorProto { optional float g = 2; optional float b = 3; optional float a = 4; -} \ No newline at end of file +} -- cgit v1.2.3-59-g8ed1b From 5d89c1d614426144b6430868a69db2b29b179213 Mon Sep 17 00:00:00 2001 From: David Sodman Date: Thu, 14 Dec 2017 15:54:51 -0800 Subject: SF: use shared_ptr to track hwcLayer Add a wrapper class and use std::shared_ptr to track instances of hwcLayer. This is necessary because the calculation of data for HWComposer is done in Layer and the processing of that data is done in SurfaceFlinger, and we need to make sure that the hwcLayer is not destroyed by Layer while or before being used by SurfaceFlinger. Merged-in: Icc7c002b84aaded1966d24aa8f849b47f51d2efb Test: Compile/Boot Change-Id: Icc7c002b84aaded1966d24aa8f849b47f51d2efb --- services/surfaceflinger/BufferLayer.cpp | 12 +++++------ services/surfaceflinger/ColorLayer.cpp | 8 ++++---- services/surfaceflinger/Layer.cpp | 36 ++++++++++++++++----------------- services/surfaceflinger/Layer.h | 10 ++++++++- services/surfaceflinger/LayerBE.h | 29 ++++++++++++++++++++++++-- 5 files changed, 64 insertions(+), 31 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index e0ea55117e..a5169ba7a4 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -575,14 +575,14 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) auto hwcId = displayDevice->getHwcDisplayId(); auto& hwcInfo = getBE().mHwcLayers[hwcId]; auto& hwcLayer = hwcInfo.layer; - auto error = hwcLayer->setVisibleRegion(visible); + 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(error)); visible.dump(LOG_TAG); } - error = hwcLayer->setSurfaceDamage(surfaceDamageRegion); + 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(error)); @@ -593,7 +593,7 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) if (getBE().compositionInfo.hwc.sidebandStream.get()) { setCompositionType(hwcId, HWC2::Composition::Sideband); ALOGV("[%s] Requesting Sideband composition", mName.string()); - error = hwcLayer->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle()); + error = (*hwcLayer)->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle()); if (error != HWC2::Error::None) { ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(), getBE().compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(), @@ -612,14 +612,14 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) } ALOGV("setPerFrameData: dataspace = %d", mDrawingState.dataSpace); - error = hwcLayer->setDataspace(mDrawingState.dataSpace); + error = (*hwcLayer)->setDataspace(mDrawingState.dataSpace); if (error != HWC2::Error::None) { ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mDrawingState.dataSpace, to_string(error).c_str(), static_cast(error)); } const HdrMetadata& metadata = mConsumer->getCurrentHdrMetadata(); - error = hwcLayer->setHdrMetadata(metadata); + error = (*hwcLayer)->setHdrMetadata(metadata); if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) { ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), to_string(error).c_str(), static_cast(error)); @@ -631,7 +631,7 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) &hwcBuffer); auto acquireFence = mConsumer->getCurrentFence(); - error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence); + error = (*hwcLayer)->setBuffer(hwcSlot, hwcBuffer, acquireFence); if (error != HWC2::Error::None) { ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), getBE().compositionInfo.mBuffer->handle, to_string(error).c_str(), diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 80a90a7d31..911b5a1b90 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -68,7 +68,7 @@ void ColorLayer::setPerFrameData(const sp& displayDevice) { auto hwcId = displayDevice->getHwcDisplayId(); auto& hwcInfo = getBE().mHwcLayers[hwcId]; auto& hwcLayer = hwcInfo.layer; - auto error = hwcLayer->setVisibleRegion(visible); + 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(error)); @@ -77,14 +77,14 @@ void ColorLayer::setPerFrameData(const sp& displayDevice) { setCompositionType(hwcId, HWC2::Composition::SolidColor); - error = hwcLayer->setDataspace(mDrawingState.dataSpace); + error = (*hwcLayer)->setDataspace(mDrawingState.dataSpace); if (error != HWC2::Error::None) { ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mDrawingState.dataSpace, to_string(error).c_str(), static_cast(error)); } half4 color = getColor(); - error = hwcLayer->setColor({static_cast(std::round(255.0f * color.r)), + error = (*hwcLayer)->setColor({static_cast(std::round(255.0f * color.r)), static_cast(std::round(255.0f * color.g)), static_cast(std::round(255.0f * color.b)), 255}); if (error != HWC2::Error::None) { @@ -93,7 +93,7 @@ void ColorLayer::setPerFrameData(const sp& displayDevice) { } // Clear out the transform, because it doesn't make sense absent a source buffer - error = hwcLayer->setTransform(HWC2::Transform::None); + 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(error)); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 610423047b..7abec882e1 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -221,15 +221,14 @@ sp Layer::getHandle() { bool Layer::createHwcLayer(HWComposer* hwc, int32_t hwcId) { LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(hwcId) != 0, "Already have a layer for hwcId %d", hwcId); - HWC2::Layer* layer = hwc->createLayer(hwcId); + + std::shared_ptr layer(new LayerContainer(hwc, hwcId)); if (!layer) { return false; } LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers[hwcId]; hwcInfo.hwc = hwc; hwcInfo.layer = layer; - layer->setLayerDestroyedListener( - [this, hwcId](HWC2::Layer* /*layer*/) { getBE().mHwcLayers.erase(hwcId); }); return true; } @@ -240,11 +239,12 @@ bool Layer::destroyHwcLayer(int32_t hwcId) { 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(getBE().mHwcLayers.count(hwcId) != 0, - "Stale layer entry in getBE().mHwcLayers"); + hwcInfo.layer = nullptr; + + if (getBE().mHwcLayers.count(hwcId) == 1) { + getBE().mHwcLayers.erase(hwcId); + } + return true; } @@ -503,7 +503,7 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z blendMode = mPremultipliedAlpha ? HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage; } - auto error = hwcLayer->setBlendMode(blendMode); + auto error = (*hwcLayer)->setBlendMode(blendMode); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set blend mode %s:" " %s (%d)", @@ -551,7 +551,7 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z } const Transform& tr(displayDevice->getTransform()); Rect transformedFrame = tr.transform(frame); - error = hwcLayer->setDisplayFrame(transformedFrame); + 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, @@ -561,7 +561,7 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z } FloatRect sourceCrop = computeCrop(displayDevice); - error = hwcLayer->setSourceCrop(sourceCrop); + error = (*hwcLayer)->setSourceCrop(sourceCrop); if (error != HWC2::Error::None) { ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: " "%s (%d)", @@ -572,13 +572,13 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z } float alpha = static_cast(getAlpha()); - error = hwcLayer->setPlaneAlpha(alpha); + 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(error)); - error = hwcLayer->setZOrder(z); + 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(error)); @@ -591,7 +591,7 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z appId = parentState.appId; } - error = hwcLayer->setInfo(type, appId); + error = (*hwcLayer)->setInfo(type, appId); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)", mName.string(), static_cast(error)); @@ -640,7 +640,7 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z } else { auto transform = static_cast(orientation); hwcInfo.transform = transform; - auto error = hwcLayer->setTransform(transform); + auto error = (*hwcLayer)->setTransform(transform); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set transform %s: " "%s (%d)", @@ -693,7 +693,7 @@ void Layer::updateCursorPosition(const sp& displayDevice) { auto& displayTransform(displayDevice->getTransform()); auto position = displayTransform.transform(frame); - auto error = getBE().mHwcLayers[hwcId].layer->setCursorPosition(position.left, + auto error = (*getBE().mHwcLayers[hwcId].layer)->setCursorPosition(position.left, position.top); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set cursor position " @@ -737,13 +737,13 @@ void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callI } auto& hwcInfo = getBE().mHwcLayers[hwcId]; auto& hwcLayer = hwcInfo.layer; - ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(), to_string(type).c_str(), + ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", (*hwcLayer)->getId(), to_string(type).c_str(), static_cast(callIntoHwc)); if (hwcInfo.compositionType != type) { ALOGV(" actually setting"); hwcInfo.compositionType = type; if (callIntoHwc) { - auto error = hwcLayer->setCompositionType(type); + auto error = (*hwcLayer)->setCompositionType(type); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set " "composition type %s: %s (%d)", diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 9c4f1cee1e..9187b9f5d3 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -435,7 +435,15 @@ public: if (getBE().mHwcLayers.count(hwcId) == 0) { return nullptr; } - return getBE().mHwcLayers[hwcId].layer; + return *(getBE().mHwcLayers[hwcId].layer.get()); + } + + bool setHwcLayer(int32_t hwcId) { + if (getBE().mHwcLayers.count(hwcId) == 0) { + return false; + } + getBE().compositionInfo.hwc.hwcLayer = getBE().mHwcLayers[hwcId].layer; + return true; } // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index d0cc8e7419..1652e8da91 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -29,12 +29,37 @@ namespace android { +class LayerContainer +{ + public: + LayerContainer(HWComposer* hwc, int32_t hwcId) : mHwc(hwc), mHwcId(hwcId) { + mLayer = hwc->createLayer(hwcId); + } + + ~LayerContainer() { + mHwc->destroyLayer(mHwcId, mLayer); + } + + HWC2::Layer* operator->() { + return mLayer; + } + + operator HWC2::Layer*const () const { + return mLayer; + } + + private: + HWComposer* mHwc; + int32_t mHwcId; + HWC2::Layer* mLayer; +}; + struct CompositionInfo { HWC2::Composition compositionType; sp mBuffer = nullptr; int mBufferSlot = BufferQueue::INVALID_BUFFER_SLOT; struct { - HWC2::Layer* hwcLayer; + std::shared_ptr hwcLayer; int32_t hwid = -1; sp fence; HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid; @@ -74,7 +99,7 @@ public: transform(HWC2::Transform::None) {} HWComposer* hwc; - HWC2::Layer* layer; + std::shared_ptr layer; bool forceClientComposition; HWC2::Composition compositionType; bool clearClientTarget; -- cgit v1.2.3-59-g8ed1b From b8af792fdfc056ca3743fc98dd88cd19468e0df7 Mon Sep 17 00:00:00 2001 From: David Sodman Date: Thu, 21 Dec 2017 15:17:55 -0800 Subject: SF: Add onLayerDisplayed method to LayerBE Add onLayerDisplayed method to LayerBE class and make the data for the class private. Merged-in: I2a5b03d542d46fc0c2e1d6d725fb87580980427d Test: Compile/Run manually Change-Id: I2a5b03d542d46fc0c2e1d6d725fb87580980427d --- services/surfaceflinger/Android.bp | 1 + services/surfaceflinger/Layer.cpp | 8 +-- services/surfaceflinger/LayerBE.cpp | 81 ++++++++++++++++++++++++++++++ services/surfaceflinger/LayerBE.h | 20 +++++++- services/surfaceflinger/SurfaceFlinger.cpp | 4 +- 5 files changed, 105 insertions(+), 9 deletions(-) create mode 100644 services/surfaceflinger/LayerBE.cpp (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index ff994f515c..cba94d2c97 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -103,6 +103,7 @@ filegroup { "FrameTracker.cpp", "GpuService.cpp", "Layer.cpp", + "LayerBE.cpp", "LayerProtoHelper.cpp", "LayerRejecter.cpp", "LayerStats.cpp", diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index b78ef97681..e50395539a 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -61,11 +61,6 @@ namespace android { -LayerBE::LayerBE() - : mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) { -} - - int32_t Layer::sSequence = 1; Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& name, uint32_t w, @@ -96,7 +91,8 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n mQueueItems(), mLastFrameNumberReceived(0), mAutoRefresh(false), - mFreezeGeometryUpdates(false) { + mFreezeGeometryUpdates(false), + mBE{this} { mCurrentCrop.makeInvalid(); diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp new file mode 100644 index 0000000000..22e38aa435 --- /dev/null +++ b/services/surfaceflinger/LayerBE.cpp @@ -0,0 +1,81 @@ +/* + * 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 "LayerBE" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "Layer.h" + +namespace android { + +LayerBE::LayerBE(Layer* layer) + : mLayer(layer), + mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) { + compositionInfo.layer = this; +} + +void LayerBE::onLayerDisplayed(const sp& releaseFence) { + mLayer->onLayerDisplayed(releaseFence); +} + +void CompositionInfo::dumpHwc(const char* tag) const { + ALOGV("[%s]\thwcLayer=%p", tag, static_cast(*hwc.hwcLayer)); + ALOGV("[%s]\tfence=%p", tag, hwc.fence.get()); + ALOGV("[%s]\ttransform=%d", tag, hwc.transform); + ALOGV("[%s]\tz=%d", tag, hwc.z); + ALOGV("[%s]\ttype=%d", tag, hwc.type); + ALOGV("[%s]\tappId=%d", tag, hwc.appId); + ALOGV("[%s]\tdisplayFrame=%4d %4d %4d %4d", tag, hwc.displayFrame.left, hwc.displayFrame.top, hwc.displayFrame.right, hwc.displayFrame.bottom); + ALOGV("[%s]\talpha=%.3f", tag, hwc.alpha); + ALOGV("[%s]\tsourceCrop=%6.1f %6.1f %6.1f %6.1f", tag, hwc.sourceCrop.left, hwc.sourceCrop.top, hwc.sourceCrop.right, hwc.sourceCrop.bottom); + + std::string label = tag; + label+=":visibleRegion"; + hwc.visibleRegion.dump(label.c_str()); + label = tag; + label+=":surfaceDamage"; + hwc.surfaceDamage.dump(label.c_str()); +} + +void CompositionInfo::dumpRe(const char* tag) const { + ALOGV("[%s]\tblackoutLayer=%d", tag, re.blackoutLayer); + ALOGV("[%s]\tclearArea=%d", tag, re.clearArea); + ALOGV("[%s]\tpreMultipliedAlpha=%d", tag, re.preMultipliedAlpha); + ALOGV("[%s]\topaque=%d\n", tag, re.opaque); + ALOGV("[%s]\ttexture:name(%d), target(%d), size(%d/%d)", tag, re.texture.getTextureName(), re.texture.getTextureTarget(), (unsigned int)re.texture.getWidth(), (unsigned int)re.texture.getHeight()); + ALOGV("[%s]\tuseIdentityTransform=%d\n", tag, re.useIdentityTransform); +} + +void CompositionInfo::dump(const char* tag) const { + ALOGV("[%s] CompositionInfo", tag); + ALOGV("[%s]\tLayerName: %s", tag, layerName.c_str()); + ALOGV("[%s]\tCompositionType: %d", tag, compositionType); + ALOGV("[%s]\tmBuffer = %p", tag, mBuffer.get()); + ALOGV("[%s]\tmBufferSlot=%d", tag, mBufferSlot); + switch (compositionType) { + case HWC2::Composition::Device: + dumpHwc(tag); + break; + case HWC2::Composition::Client: + dumpRe(tag); + default: + break; + } +} + +}; // namespace android diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 14619f6044..75766bfb2b 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -30,6 +30,8 @@ namespace android { +class LayerBE; + class LayerContainer { public: @@ -56,9 +58,11 @@ class LayerContainer }; struct CompositionInfo { + std::string layerName; HWC2::Composition compositionType; sp mBuffer = nullptr; int mBufferSlot = BufferQueue::INVALID_BUFFER_SLOT; + LayerBE* layer = nullptr; struct { std::shared_ptr hwcLayer; int32_t hwid = -1; @@ -87,12 +91,26 @@ struct CompositionInfo { Texture texture; bool useIdentityTransform = false; } re; + + void dump(const char* tag) const; + void dumpHwc(const char* tag) const; + void dumpRe(const char* tag) const; }; class LayerBE { public: - LayerBE(); + friend class Layer; + friend class BufferLayer; + friend class ColorLayer; + friend class SurfaceFlinger; + + LayerBE(Layer* layer); + + void onLayerDisplayed(const sp& releaseFence); + Mesh& getMesh() { return mMesh; } +private: + Layer*const mLayer; // The mesh used to draw the layer in GLES composition mode Mesh mMesh; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c8a9f691ae..7ae5b219a1 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2034,7 +2034,7 @@ void SurfaceFlinger::postFramebuffer() displayDevice->getClientTargetAcquireFence()); } - layer->onLayerDisplayed(releaseFence); + layer->getBE().onLayerDisplayed(releaseFence); } // We've got a list of layers needing fences, that are disjoint with @@ -2043,7 +2043,7 @@ void SurfaceFlinger::postFramebuffer() if (!displayDevice->getLayersNeedingFences().isEmpty()) { sp presentFence = getBE().mHwc->getPresentFence(hwcId); for (auto& layer : displayDevice->getLayersNeedingFences()) { - layer->onLayerDisplayed(presentFence); + layer->getBE().onLayerDisplayed(presentFence); } } -- cgit v1.2.3-59-g8ed1b From 2b727ac817c79d1e7342fb364d4b1d0512b5060d Mon Sep 17 00:00:00 2001 From: David Sodman Date: Thu, 21 Dec 2017 14:28:08 -0800 Subject: SF: Add LayerName to CompositionInfo Add layerName to CompositionInfo for tracking/debug purposes Test: Compile Merged-Id: I445a32f2a095dae435581888171a46082880c1e4 Change-Id: I445a32f2a095dae435581888171a46082880c1e4 --- services/surfaceflinger/Layer.cpp | 2 +- services/surfaceflinger/LayerBE.cpp | 3 ++- services/surfaceflinger/LayerBE.h | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e50395539a..ba2d0a0b76 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -92,7 +92,7 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n mLastFrameNumberReceived(0), mAutoRefresh(false), mFreezeGeometryUpdates(false), - mBE{this} { + mBE{this, name.string()} { mCurrentCrop.makeInvalid(); diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp index 22e38aa435..5287fe1dfd 100644 --- a/services/surfaceflinger/LayerBE.cpp +++ b/services/surfaceflinger/LayerBE.cpp @@ -23,10 +23,11 @@ namespace android { -LayerBE::LayerBE(Layer* layer) +LayerBE::LayerBE(Layer* layer, std::string layerName) : mLayer(layer), mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) { compositionInfo.layer = this; + compositionInfo.layerName = layerName; } void LayerBE::onLayerDisplayed(const sp& releaseFence) { diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 75766bfb2b..981f756664 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -104,7 +104,7 @@ public: friend class ColorLayer; friend class SurfaceFlinger; - LayerBE(Layer* layer); + LayerBE(Layer* layer, std::string layerName); void onLayerDisplayed(const sp& releaseFence); Mesh& getMesh() { return mMesh; } -- cgit v1.2.3-59-g8ed1b From 4b7c4bc2e493164d6c131f50e8a2a88521ecc0ad Mon Sep 17 00:00:00 2001 From: David Sodman Date: Fri, 17 Nov 2017 12:13:59 -0800 Subject: SF: Use CompositionInfo to program HWComposer Test: Build and run manually Merged-Id: I3a4fd676781d0b7db1665430e0d84a6bc9b83f60 Change-Id: I3a4fd676781d0b7db1665430e0d84a6bc9b83f60 --- services/surfaceflinger/BufferLayer.cpp | 53 ++-------- services/surfaceflinger/ColorLayer.cpp | 32 ++---- services/surfaceflinger/Layer.cpp | 155 +++++++++++++++++++++-------- services/surfaceflinger/Layer.h | 1 + services/surfaceflinger/LayerBE.h | 2 + services/surfaceflinger/SurfaceFlinger.cpp | 15 ++- 6 files changed, 142 insertions(+), 116 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index a6caf29df8..916576af20 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -593,32 +593,14 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) const auto& viewport = displayDevice->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); auto hwcId = displayDevice->getHwcDisplayId(); - auto& hwcInfo = getBE().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(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(error)); - surfaceDamageRegion.dump(LOG_TAG); - } + getBE().compositionInfo.hwc.visibleRegion = visible; + getBE().compositionInfo.hwc.surfaceDamage = surfaceDamageRegion; // Sideband layers if (getBE().compositionInfo.hwc.sidebandStream.get()) { setCompositionType(hwcId, HWC2::Composition::Sideband); - ALOGV("[%s] Requesting Sideband composition", mName.string()); - error = (*hwcLayer)->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle()); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(), - getBE().compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(), - static_cast(error)); - } + getBE().compositionInfo.compositionType = HWC2::Composition::Sideband; return; } @@ -631,32 +613,13 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) setCompositionType(hwcId, HWC2::Composition::Device); } - ALOGV("setPerFrameData: dataspace = %d", mDrawingState.dataSpace); - error = (*hwcLayer)->setDataspace(mDrawingState.dataSpace); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mDrawingState.dataSpace, - to_string(error).c_str(), static_cast(error)); - } - - const HdrMetadata& metadata = mConsumer->getCurrentHdrMetadata(); - error = (*hwcLayer)->setHdrMetadata(metadata); - if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) { - ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast(error)); - } - - uint32_t hwcSlot = 0; - sp hwcBuffer; - getBE().mHwcLayers[hwcId].bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, &hwcSlot, - &hwcBuffer); + getBE().compositionInfo.hwc.dataspace = mDrawingState.dataSpace; + getBE().compositionInfo.hwc.hdrMetadata = mConsumer->getCurrentHdrMetadata(); auto acquireFence = mConsumer->getCurrentFence(); - error = (*hwcLayer)->setBuffer(hwcSlot, hwcBuffer, acquireFence); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), - getBE().compositionInfo.mBuffer->handle, to_string(error).c_str(), - static_cast(error)); - } + getBE().compositionInfo.mBufferSlot = mActiveBufferSlot; + getBE().compositionInfo.mBuffer = mActiveBuffer; + getBE().compositionInfo.hwc.fence = acquireFence; } bool BufferLayer::isOpaque(const Layer::State& s) const { diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 71975c8f73..5990a61bc5 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -77,38 +77,18 @@ void ColorLayer::setPerFrameData(const sp& displayDevice) { const auto& viewport = displayDevice->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); auto hwcId = displayDevice->getHwcDisplayId(); - auto& hwcInfo = getBE().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(error)); - visible.dump(LOG_TAG); - } + getBE().compositionInfo.hwc.visibleRegion = visible; + getBE().compositionInfo.hwc.dataspace = mDrawingState.dataSpace; setCompositionType(hwcId, HWC2::Composition::SolidColor); - error = (*hwcLayer)->setDataspace(mDrawingState.dataSpace); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mDrawingState.dataSpace, - to_string(error).c_str(), static_cast(error)); - } - half4 color = getColor(); - error = (*hwcLayer)->setColor({static_cast(std::round(255.0f * color.r)), - static_cast(std::round(255.0f * color.g)), - static_cast(std::round(255.0f * color.b)), 255}); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set color: %s (%d)", mName.string(), to_string(error).c_str(), - static_cast(error)); - } + getBE().compositionInfo.hwc.color = { static_cast(std::round(255.0f * color.r)), + static_cast(std::round(255.0f * color.g)), + static_cast(std::round(255.0f * color.b)), 255 }; // 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(error)); - } + getBE().compositionInfo.hwc.transform = HWC2::Transform::None; } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index ba2d0a0b76..b072213102 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -490,8 +490,6 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z hwcInfo.forceClientComposition = true; } - auto& hwcLayer = hwcInfo.layer; - // this gives us only the "orientation" component of the transform const State& s(getDrawingState()); auto blendMode = HWC2::BlendMode::None; @@ -499,12 +497,7 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z 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(error)); + getBE().compositionInfo.hwc.blendMode = blendMode; // apply the layer's transform, followed by the display's global transform // here we're guaranteed that the layer's transform preserves rects @@ -547,36 +540,15 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z } const Transform& tr(displayDevice->getTransform()); 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(error)); - } else { - hwcInfo.displayFrame = transformedFrame; - } + getBE().compositionInfo.hwc.displayFrame = transformedFrame; FloatRect sourceCrop = computeCrop(displayDevice); - 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(error)); - } else { - hwcInfo.sourceCrop = sourceCrop; - } + getBE().compositionInfo.hwc.sourceCrop = sourceCrop; float alpha = static_cast(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(error)); + getBE().compositionInfo.hwc.alpha = alpha; - 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(error)); + getBE().compositionInfo.hwc.z = z; int type = s.type; int appId = s.appId; @@ -587,9 +559,8 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z appId = parentState.appId; } - error = (*hwcLayer)->setInfo(type, appId); - ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)", mName.string(), - static_cast(error)); + getBE().compositionInfo.hwc.type = type; + getBE().compositionInfo.hwc.appId = appId; /* * Transformations are applied in this order: @@ -636,12 +607,109 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z } else { auto transform = static_cast(orientation); hwcInfo.transform = transform; - auto error = (*hwcLayer)->setTransform(transform); + getBE().compositionInfo.hwc.transform = transform; + } +} + +void Layer::configureHwcLayer(const sp& displayDevice) { + ATRACE_CALL(); + + auto hwcId = displayDevice->getHwcDisplayId(); + auto& hwcInfo = getBE().mHwcLayers[hwcId]; + auto& hwcLayer = hwcInfo.layer; + + auto error = (*hwcLayer)->setBlendMode(getBE().compositionInfo.hwc.blendMode); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set blend mode %s:" + " %s (%d)", + mName.string(), + to_string(getBE().compositionInfo.hwc.blendMode).c_str(), to_string(error).c_str(), + static_cast(error)); + + error = (*hwcLayer)->setDisplayFrame(getBE().compositionInfo.hwc.displayFrame); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set the display frame [%d, %d, %d, %d] %s (%d)", + mName.string(), + getBE().compositionInfo.hwc.displayFrame.left, + getBE().compositionInfo.hwc.displayFrame.right, + getBE().compositionInfo.hwc.displayFrame.top, + getBE().compositionInfo.hwc.displayFrame.bottom, + to_string(error).c_str(), static_cast(error)); + + + error = (*hwcLayer)->setPlaneAlpha(getBE().compositionInfo.hwc.alpha); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set plane alpha %.3f: " + "%s (%d)", + mName.string(), getBE().compositionInfo.hwc.alpha, + to_string(error).c_str(), static_cast(error)); + + error = (*hwcLayer)->setSourceCrop(getBE().compositionInfo.hwc.sourceCrop); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: %s (%d)", + mName.string(), + getBE().compositionInfo.hwc.sourceCrop.left, + getBE().compositionInfo.hwc.sourceCrop.right, + getBE().compositionInfo.hwc.sourceCrop.top, + getBE().compositionInfo.hwc.sourceCrop.bottom, + to_string(error).c_str(), static_cast(error)); + + error = (*hwcLayer)->setTransform(getBE().compositionInfo.hwc.transform); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set transform %s: " + "%s (%d)", + mName.string(), + to_string(getBE().compositionInfo.hwc.transform).c_str(), to_string(error).c_str(), + static_cast(error)); + + error = (*hwcLayer)->setZOrder(getBE().compositionInfo.hwc.z); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set Z %u: %s (%d)", + mName.string(), getBE().compositionInfo.hwc.z, + to_string(error).c_str(), static_cast(error)); + + error = (*hwcLayer)->setInfo(getBE().compositionInfo.hwc.type, getBE().compositionInfo.hwc.appId); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set info (%d)", + mName.string(), static_cast(error)); + + error = (*hwcLayer)->setVisibleRegion(getBE().compositionInfo.hwc.visibleRegion); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set visible region: %s (%d)", + mName.string(), to_string(error).c_str(), static_cast(error)); + + error = (*hwcLayer)->setSurfaceDamage(getBE().compositionInfo.hwc.surfaceDamage); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set surface damage: %s (%d)", + mName.string(), to_string(error).c_str(), static_cast(error)); + + error = (*hwcLayer)->setCompositionType(getBE().compositionInfo.compositionType); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set composition type: %s (%d)", + mName.string(), to_string(error).c_str(), static_cast(error)); + + error = (*hwcLayer)->setDataspace(getBE().compositionInfo.hwc.dataspace); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set dataspace: %s (%d)", + mName.string(), to_string(error).c_str(), static_cast(error)); + + error = (*hwcLayer)->setHdrMetadata(getBE().compositionInfo.hwc.hdrMetadata); + if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) { + ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), + to_string(error).c_str(), static_cast(error)); + } + + error = (*hwcLayer)->setColor(getBE().compositionInfo.hwc.color); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set color: %s (%d)", + mName.string(), to_string(error).c_str(), static_cast(error)); + + if (getBE().compositionInfo.hwc.fence) { + error = (*hwcLayer)->setBuffer(getBE().compositionInfo.mBufferSlot, + getBE().compositionInfo.mBuffer, getBE().compositionInfo.hwc.fence); 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(error)); + "[%s] Failed to set buffer: %s (%d)", + mName.string(), to_string(error).c_str(), static_cast(error)); } } @@ -1488,12 +1556,11 @@ void Layer::miniDump(String8& result, int32_t hwcId) const { result.appendFormat(" %s\n", name.string()); const Layer::State& layerState(getDrawingState()); - const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(hwcId); result.appendFormat(" %10d | ", layerState.z); result.appendFormat("%10s | ", to_string(getCompositionType(hwcId)).c_str()); - const Rect& frame = hwcInfo.displayFrame; + const Rect& frame = getBE().compositionInfo.hwc.displayFrame; result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom); - const FloatRect& crop = hwcInfo.sourceCrop; + const FloatRect& crop = getBE().compositionInfo.hwc.sourceCrop; result.appendFormat("%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top, crop.right, crop.bottom); result.append("- - - - - - - - - - - - - - - - - - - - "); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index cac1c20512..87f9489fa2 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -309,6 +309,7 @@ public: virtual void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {} void setGeometry(const sp& displayDevice, uint32_t z); + void configureHwcLayer(const sp& displayDevice); void forceClientComposition(int32_t hwcId); bool getForceClientComposition(int32_t hwcId); virtual void setPerFrameData(const sp& displayDevice) = 0; diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 854cdd692b..06c88a4e16 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -19,6 +19,7 @@ #include #include +#include #include #include "SurfaceFlinger.h" @@ -80,6 +81,7 @@ struct CompositionInfo { sp sidebandStream; android_dataspace dataspace; hwc_color_t color; + HdrMetadata hdrMetadata; } hwc; struct { Mesh* mesh; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 2c0dec9094..8d5c496353 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -647,6 +647,7 @@ void SurfaceFlinger::init() { // set initial conditions (e.g. unblank default device) initializeDisplays(); + ALOGV("Displays initialized"); getBE().mRenderEngine->primeCache(); @@ -1971,6 +1972,18 @@ void SurfaceFlinger::setUpHWComposer() { mPreviousColorMatrix = colorMatrix; + for (size_t dpy = 0; dpy < mDisplays.size(); dpy++) { + sp displayDevice(mDisplays[dpy]); + const auto hwcId = displayDevice->getHwcDisplayId(); + if (hwcId >= 0) { + const Vector>& currentLayers( + displayDevice->getVisibleLayersSortedByZ()); + for (auto& layer : currentLayers) { + layer->configureHwcLayer(displayDevice); + } + } + } + for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { auto& displayDevice = mDisplays[displayId]; if (!displayDevice->isDisplayOn()) { @@ -2762,6 +2775,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev } bool hasClientComposition = getBE().mHwc->hasClientComposition(hwcId); + ATRACE_INT("hasClientComposition", hasClientComposition); if (hasClientComposition) { ALOGV("hasClientComposition"); @@ -4872,7 +4886,6 @@ void SurfaceFlinger::traverseLayersInDisplay(const sp& hw, }; // namespace android - #if defined(__gl_h_) #error "don't include gl/gl.h in this file" #endif -- cgit v1.2.3-59-g8ed1b From 5691283a09f81660448ce4c4983bd97570c4a897 Mon Sep 17 00:00:00 2001 From: David Sodman Date: Tue, 28 Nov 2017 10:27:38 -0800 Subject: SF: Move config of HWComposer to setupHwComposer Eliminate the setupFramebuffer function from Layer and use setupHwComposer to actually setup the HWComposer. Additionally, move preComposition and RebuildLayerStacks into handleMessageInvalidate, as they are more frontend processing. Test: Compile/Run manually Merged-In: Iffffbd8d044513ef3586ae2d25bdd76e077ed1af Change-Id: Iffffbd8d044513ef3586ae2d25bdd76e077ed1af --- services/surfaceflinger/BufferLayer.cpp | 1 + services/surfaceflinger/Layer.cpp | 139 +----------- services/surfaceflinger/Layer.h | 1 - services/surfaceflinger/LayerBE.h | 2 + services/surfaceflinger/SurfaceFlinger.cpp | 331 +++++++++++++++++++++-------- services/surfaceflinger/SurfaceFlinger.h | 6 + 6 files changed, 261 insertions(+), 219 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 579f7ecec4..616d22e0fe 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -620,6 +620,7 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) getBE().compositionInfo.mBufferSlot = mActiveBufferSlot; getBE().compositionInfo.mBuffer = mActiveBuffer; getBE().compositionInfo.hwc.fence = acquireFence; + getBE().compositionInfo.updateBuffer = true; } bool BufferLayer::isOpaque(const Layer::State& s) const { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index b072213102..5083099841 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -483,6 +483,9 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z const auto hwcId = displayDevice->getHwcDisplayId(); auto& hwcInfo = getBE().mHwcLayers[hwcId]; + // Need to program geometry parts + getBE().compositionInfo.hwc.skipGeometry = false; + // enable this layer hwcInfo.forceClientComposition = false; @@ -603,7 +606,7 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z const uint32_t orientation = transform.getOrientation(); if (orientation & Transform::ROT_INVALID || extremeScaling) { // we can only handle simple transformation - hwcInfo.forceClientComposition = true; + getBE().mHwcLayers[hwcId].compositionType = HWC2::Composition::Client; } else { auto transform = static_cast(orientation); hwcInfo.transform = transform; @@ -611,108 +614,6 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z } } -void Layer::configureHwcLayer(const sp& displayDevice) { - ATRACE_CALL(); - - auto hwcId = displayDevice->getHwcDisplayId(); - auto& hwcInfo = getBE().mHwcLayers[hwcId]; - auto& hwcLayer = hwcInfo.layer; - - auto error = (*hwcLayer)->setBlendMode(getBE().compositionInfo.hwc.blendMode); - ALOGE_IF(error != HWC2::Error::None, - "[%s] Failed to set blend mode %s:" - " %s (%d)", - mName.string(), - to_string(getBE().compositionInfo.hwc.blendMode).c_str(), to_string(error).c_str(), - static_cast(error)); - - error = (*hwcLayer)->setDisplayFrame(getBE().compositionInfo.hwc.displayFrame); - ALOGE_IF(error != HWC2::Error::None, - "[%s] Failed to set the display frame [%d, %d, %d, %d] %s (%d)", - mName.string(), - getBE().compositionInfo.hwc.displayFrame.left, - getBE().compositionInfo.hwc.displayFrame.right, - getBE().compositionInfo.hwc.displayFrame.top, - getBE().compositionInfo.hwc.displayFrame.bottom, - to_string(error).c_str(), static_cast(error)); - - - error = (*hwcLayer)->setPlaneAlpha(getBE().compositionInfo.hwc.alpha); - ALOGE_IF(error != HWC2::Error::None, - "[%s] Failed to set plane alpha %.3f: " - "%s (%d)", - mName.string(), getBE().compositionInfo.hwc.alpha, - to_string(error).c_str(), static_cast(error)); - - error = (*hwcLayer)->setSourceCrop(getBE().compositionInfo.hwc.sourceCrop); - ALOGE_IF(error != HWC2::Error::None, - "[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: %s (%d)", - mName.string(), - getBE().compositionInfo.hwc.sourceCrop.left, - getBE().compositionInfo.hwc.sourceCrop.right, - getBE().compositionInfo.hwc.sourceCrop.top, - getBE().compositionInfo.hwc.sourceCrop.bottom, - to_string(error).c_str(), static_cast(error)); - - error = (*hwcLayer)->setTransform(getBE().compositionInfo.hwc.transform); - ALOGE_IF(error != HWC2::Error::None, - "[%s] Failed to set transform %s: " - "%s (%d)", - mName.string(), - to_string(getBE().compositionInfo.hwc.transform).c_str(), to_string(error).c_str(), - static_cast(error)); - - error = (*hwcLayer)->setZOrder(getBE().compositionInfo.hwc.z); - ALOGE_IF(error != HWC2::Error::None, - "[%s] Failed to set Z %u: %s (%d)", - mName.string(), getBE().compositionInfo.hwc.z, - to_string(error).c_str(), static_cast(error)); - - error = (*hwcLayer)->setInfo(getBE().compositionInfo.hwc.type, getBE().compositionInfo.hwc.appId); - ALOGE_IF(error != HWC2::Error::None, - "[%s] Failed to set info (%d)", - mName.string(), static_cast(error)); - - error = (*hwcLayer)->setVisibleRegion(getBE().compositionInfo.hwc.visibleRegion); - ALOGE_IF(error != HWC2::Error::None, - "[%s] Failed to set visible region: %s (%d)", - mName.string(), to_string(error).c_str(), static_cast(error)); - - error = (*hwcLayer)->setSurfaceDamage(getBE().compositionInfo.hwc.surfaceDamage); - ALOGE_IF(error != HWC2::Error::None, - "[%s] Failed to set surface damage: %s (%d)", - mName.string(), to_string(error).c_str(), static_cast(error)); - - error = (*hwcLayer)->setCompositionType(getBE().compositionInfo.compositionType); - ALOGE_IF(error != HWC2::Error::None, - "[%s] Failed to set composition type: %s (%d)", - mName.string(), to_string(error).c_str(), static_cast(error)); - - error = (*hwcLayer)->setDataspace(getBE().compositionInfo.hwc.dataspace); - ALOGE_IF(error != HWC2::Error::None, - "[%s] Failed to set dataspace: %s (%d)", - mName.string(), to_string(error).c_str(), static_cast(error)); - - error = (*hwcLayer)->setHdrMetadata(getBE().compositionInfo.hwc.hdrMetadata); - if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) { - ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast(error)); - } - - error = (*hwcLayer)->setColor(getBE().compositionInfo.hwc.color); - ALOGE_IF(error != HWC2::Error::None, - "[%s] Failed to set color: %s (%d)", - mName.string(), to_string(error).c_str(), static_cast(error)); - - if (getBE().compositionInfo.hwc.fence) { - error = (*hwcLayer)->setBuffer(getBE().compositionInfo.mBufferSlot, - getBE().compositionInfo.mBuffer, getBE().compositionInfo.hwc.fence); - ALOGE_IF(error != HWC2::Error::None, - "[%s] Failed to set buffer: %s (%d)", - mName.string(), to_string(error).c_str(), static_cast(error)); - } -} - void Layer::forceClientComposition(int32_t hwcId) { if (getBE().mHwcLayers.count(hwcId) == 0) { ALOGE("forceClientComposition: no HWC layer found (%d)", hwcId); @@ -794,26 +695,12 @@ void Layer::clearWithOpenGL(const RenderArea& renderArea) const { clearWithOpenGL(renderArea, 0, 0, 0, 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 = getBE().mHwcLayers[hwcId]; - auto& hwcLayer = hwcInfo.layer; - ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", (*hwcLayer)->getId(), to_string(type).c_str(), - static_cast(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(error)); - } +void Layer::setCompositionType(int32_t /*hwcId*/, HWC2::Composition type, bool /*callIntoHwc*/) { + if (getBE().compositionInfo.compositionType != type) { + ALOGV("setCompositionType: Changing compositionType from %s to %s", + to_string(getBE().compositionInfo.compositionType).c_str(), + to_string(type).c_str()); + getBE().compositionInfo.compositionType = type; } } @@ -823,11 +710,7 @@ HWC2::Composition Layer::getCompositionType(int32_t hwcId) const { // have a HWC counterpart, then it will always be Client return HWC2::Composition::Client; } - if (getBE().mHwcLayers.count(hwcId) == 0) { - ALOGE("getCompositionType called with an invalid HWC layer"); - return HWC2::Composition::Invalid; - } - return getBE().mHwcLayers.at(hwcId).compositionType; + return getBE().compositionInfo.compositionType; } void Layer::setClearClientTarget(int32_t hwcId, bool clear) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 87f9489fa2..cac1c20512 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -309,7 +309,6 @@ public: virtual void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {} void setGeometry(const sp& displayDevice, uint32_t z); - void configureHwcLayer(const sp& displayDevice); void forceClientComposition(int32_t hwcId); bool getForceClientComposition(int32_t hwcId); virtual void setPerFrameData(const sp& displayDevice) = 0; diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 06c88a4e16..767a3b3850 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -64,8 +64,10 @@ struct CompositionInfo { sp mBuffer = nullptr; int mBufferSlot = BufferQueue::INVALID_BUFFER_SLOT; LayerBE* layer = nullptr; + bool updateBuffer = false; struct { std::shared_ptr hwcLayer; + bool skipGeometry = true; int32_t hwid = -1; sp fence; HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 8d5c496353..6552781afa 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1416,7 +1416,16 @@ void SurfaceFlinger::onMessageReceived(int32_t what) { bool refreshNeeded = handleMessageTransaction(); refreshNeeded |= handleMessageInvalidate(); refreshNeeded |= mRepaintEverything; + + const nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC); + + preComposition(refreshStartTime); + rebuildLayerStacks(); + + calculateWorkingSet(); + if (refreshNeeded) { + // Signal a refresh if a transaction modified the window state, // a new buffer was latched, or if HWC has requested a full // repaint @@ -1445,6 +1454,101 @@ bool SurfaceFlinger::handleMessageInvalidate() { return handlePageFlip(); } +void SurfaceFlinger::calculateWorkingSet() { + ATRACE_CALL(); + ALOGV(__FUNCTION__); + + // build the h/w work list + if (CC_UNLIKELY(mGeometryInvalid)) { + mGeometryInvalid = false; + for (size_t dpy=0 ; dpy displayDevice(mDisplays[dpy]); + const auto hwcId = displayDevice->getHwcDisplayId(); + if (hwcId >= 0) { + const Vector>& currentLayers( + displayDevice->getVisibleLayersSortedByZ()); + for (size_t i = 0; i < currentLayers.size(); i++) { + const auto& layer = currentLayers[i]; + + if (!layer->hasHwcLayer(hwcId)) { + if (!layer->createHwcLayer(getBE().mHwc.get(), hwcId)) { + layer->forceClientComposition(hwcId); + continue; + } + } + + layer->setGeometry(displayDevice, i); + if (mDebugDisableHWC || mDebugRegion) { + layer->forceClientComposition(hwcId); + } + } + } + } + } + mat4 colorMatrix = mColorMatrix * computeSaturationMatrix() * mDaltonizer(); + + // Set the per-frame data + for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { + auto& displayDevice = mDisplays[displayId]; + const auto hwcId = displayDevice->getHwcDisplayId(); + + if (hwcId < 0) { + continue; + } + if (colorMatrix != mPreviousColorMatrix) { + status_t result = getBE().mHwc->setColorTransform(hwcId, colorMatrix); + ALOGE_IF(result != NO_ERROR, "Failed to set color transform on " + "display %zd: %d", displayId, result); + } + for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { + if ((layer->getDataSpace() == HAL_DATASPACE_BT2020_PQ || + layer->getDataSpace() == HAL_DATASPACE_BT2020_ITU_PQ) && + !displayDevice->getHdrSupport()) { + layer->forceClientComposition(hwcId); + } + + if (layer->getForceClientComposition(hwcId)) { + ALOGV("[%s] Requesting Client composition", layer->getName().string()); + layer->setCompositionType(hwcId, HWC2::Composition::Client); + continue; + } + + layer->setPerFrameData(displayDevice); + } + + if (hasWideColorDisplay) { + ColorMode newColorMode; + android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB; + + for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { + newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace, + displayDevice->getHdrSupport()); + ALOGV("layer: %s, dataspace: %s (%#x), newDataSpace: %s (%#x)", + layer->getName().string(), dataspaceDetails(layer->getDataSpace()).c_str(), + layer->getDataSpace(), dataspaceDetails(newDataSpace).c_str(), newDataSpace); + } + newColorMode = pickColorMode(newDataSpace); + + setActiveColorModeInternal(displayDevice, newColorMode); + } + } + + mPreviousColorMatrix = colorMatrix; + for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { + auto& displayDevice = mDisplays[displayId]; + for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { + auto hwcId = displayDevice->getHwcDisplayId(); + layer->getBE().compositionInfo.compositionType = layer->getCompositionType(hwcId); + if (!layer->setHwcLayer(hwcId)) { + ALOGV("Need to create HWCLayer for %s", layer->getName().string()); + } + layer->getBE().compositionInfo.hwc.hwid = hwcId; + getBE().mCompositionInfo.push_back(layer->getBE().compositionInfo); + layer->getBE().compositionInfo.hwc.hwcLayer = nullptr; + } + } +} + void SurfaceFlinger::handleMessageRefresh() { ATRACE_CALL(); @@ -1452,8 +1556,6 @@ void SurfaceFlinger::handleMessageRefresh() { nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC); - preComposition(refreshStartTime); - rebuildLayerStacks(); setUpHWComposer(); doDebugFlashRegions(); doTracing("handleRefresh"); @@ -1756,17 +1858,21 @@ void SurfaceFlinger::rebuildLayerStacks() { if (!drawRegion.isEmpty()) { layersSortedByZ.add(layer); } else { - // Clear out the HWC layer if this layer was - // previously visible, but no longer is + if (layer->hasHwcLayer(displayDevice->getHwcDisplayId())) { + // Clear out the HWC layer if this layer was + // previously visible, but no longer is + hwcLayerDestroyed = layer->destroyHwcLayer( + displayDevice->getHwcDisplayId()); + } + } + } else { + if (layer->hasHwcLayer(displayDevice->getHwcDisplayId())) { + // WM changes displayDevice->layerStack upon sleep/awake. + // Here we make sure we delete the HWC layers even if + // WM changed their layer stack. hwcLayerDestroyed = layer->destroyHwcLayer( displayDevice->getHwcDisplayId()); } - } else { - // WM changes displayDevice->layerStack upon sleep/awake. - // Here we make sure we delete the HWC layers even if - // WM changed their layer stack. - hwcLayerDestroyed = layer->destroyHwcLayer( - displayDevice->getHwcDisplayId()); } // If a layer is not going to get a release fence because @@ -1861,6 +1967,109 @@ android_dataspace SurfaceFlinger::bestTargetDataSpace( return HAL_DATASPACE_V0_SRGB; } +void SurfaceFlinger::configureDeviceComposition(const CompositionInfo& compositionInfo) const +{ + HWC2::Error error; + + if (!compositionInfo.hwc.skipGeometry) { + if (compositionInfo.hwc.blendMode != HWC2::BlendMode::Invalid) { + error = (*compositionInfo.hwc.hwcLayer)->setBlendMode(compositionInfo.hwc.blendMode); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set blend mode %s:" + " %s (%d)", + to_string(compositionInfo.hwc.blendMode).c_str(), to_string(error).c_str(), + static_cast(error)); + } + + if (compositionInfo.hwc.displayFrame.isValid()) { + error = (*compositionInfo.hwc.hwcLayer)->setDisplayFrame(compositionInfo.hwc.displayFrame); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set the display frame [%d, %d, %d, %d] %s (%d)", + compositionInfo.hwc.displayFrame.left, + compositionInfo.hwc.displayFrame.right, + compositionInfo.hwc.displayFrame.top, + compositionInfo.hwc.displayFrame.bottom, + to_string(error).c_str(), static_cast(error)); + } + + if ((compositionInfo.hwc.sourceCrop.getWidth() > 0) && (compositionInfo.hwc.sourceCrop.getHeight() > 0)) { + error = (*compositionInfo.hwc.hwcLayer)->setSourceCrop(compositionInfo.hwc.sourceCrop); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: %s (%d)", + compositionInfo.hwc.sourceCrop.left, + compositionInfo.hwc.sourceCrop.right, + compositionInfo.hwc.sourceCrop.top, + compositionInfo.hwc.sourceCrop.bottom, + to_string(error).c_str(), static_cast(error)); + } + + error = (*compositionInfo.hwc.hwcLayer)->setPlaneAlpha(compositionInfo.hwc.alpha); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set plane alpha %.3f: " + "%s (%d)", + compositionInfo.hwc.alpha, + to_string(error).c_str(), static_cast(error)); + + + error = (*compositionInfo.hwc.hwcLayer)->setZOrder(compositionInfo.hwc.z); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set Z %u: %s (%d)", + compositionInfo.hwc.z, + to_string(error).c_str(), static_cast(error)); + + error = (*compositionInfo.hwc.hwcLayer)->setInfo(compositionInfo.hwc.type, compositionInfo.hwc.appId); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set info (%d)", + static_cast(error)); + + if (compositionInfo.hwc.transform != HWC2::Transform::None) { + error = (*compositionInfo.hwc.hwcLayer)->setTransform(compositionInfo.hwc.transform); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set transform %s: " + "%s (%d)", + to_string(compositionInfo.hwc.transform).c_str(), to_string(error).c_str(), + static_cast(error)); + } + } + + if (!compositionInfo.hwc.visibleRegion.isEmpty()) { + error = (*compositionInfo.hwc.hwcLayer)->setVisibleRegion(compositionInfo.hwc.visibleRegion); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set visible region: %s (%d)", + to_string(error).c_str(), static_cast(error)); + } + + if (!compositionInfo.hwc.surfaceDamage.isEmpty()) { + error = (*compositionInfo.hwc.hwcLayer)->setSurfaceDamage(compositionInfo.hwc.surfaceDamage); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set surface damage: %s (%d)", + to_string(error).c_str(), static_cast(error)); + } + + error = (*compositionInfo.hwc.hwcLayer)->setCompositionType(compositionInfo.compositionType); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set composition type: %s (%d)", + to_string(error).c_str(), static_cast(error)); + + error = (*compositionInfo.hwc.hwcLayer)->setDataspace(compositionInfo.hwc.dataspace); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set dataspace: %s (%d)", + to_string(error).c_str(), static_cast(error)); + + error = (*compositionInfo.hwc.hwcLayer)->setHdrMetadata(compositionInfo.hwc.hdrMetadata); + ALOGE_IF(error != HWC2::Error::None && error != HWC2::Error::Unsupported, + "[SF] Failed to set hdrMetadata: %s (%d)", + to_string(error).c_str(), static_cast(error)); + + if (compositionInfo.updateBuffer) { + error = (*compositionInfo.hwc.hwcLayer)->setBuffer(compositionInfo.mBufferSlot, + compositionInfo.mBuffer, compositionInfo.hwc.fence); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set buffer: %s (%d)", + to_string(error).c_str(), static_cast(error)); + } +} + void SurfaceFlinger::setUpHWComposer() { ATRACE_CALL(); ALOGV("setUpHWComposer"); @@ -1894,94 +2103,36 @@ void SurfaceFlinger::setUpHWComposer() { } } - // build the h/w work list - if (CC_UNLIKELY(mGeometryInvalid)) { - mGeometryInvalid = false; - for (size_t dpy=0 ; dpy displayDevice(mDisplays[dpy]); - const auto hwcId = displayDevice->getHwcDisplayId(); - if (hwcId >= 0) { - const Vector>& currentLayers( - displayDevice->getVisibleLayersSortedByZ()); - for (size_t i = 0; i < currentLayers.size(); i++) { - const auto& layer = currentLayers[i]; - if (!layer->hasHwcLayer(hwcId)) { - if (!layer->createHwcLayer(getBE().mHwc.get(), hwcId)) { - layer->forceClientComposition(hwcId); - continue; - } - } - - layer->setGeometry(displayDevice, i); - if (mDebugDisableHWC || mDebugRegion) { - layer->forceClientComposition(hwcId); - } - } - } - } - } - - - mat4 colorMatrix = mColorMatrix * computeSaturationMatrix() * mDaltonizer(); - - // Set the per-frame data - for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { - auto& displayDevice = mDisplays[displayId]; - const auto hwcId = displayDevice->getHwcDisplayId(); - - if (hwcId < 0) { - continue; - } - if (colorMatrix != mPreviousColorMatrix) { - status_t result = getBE().mHwc->setColorTransform(hwcId, colorMatrix); - ALOGE_IF(result != NO_ERROR, "Failed to set color transform on " - "display %zd: %d", displayId, result); - } - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - if ((layer->getDataSpace() == HAL_DATASPACE_BT2020_PQ || - layer->getDataSpace() == HAL_DATASPACE_BT2020_ITU_PQ) && - !displayDevice->getHdrSupport()) { - layer->forceClientComposition(hwcId); - } - - if (layer->getForceClientComposition(hwcId)) { - ALOGV("[%s] Requesting Client composition", layer->getName().string()); - layer->setCompositionType(hwcId, HWC2::Composition::Client); - continue; - } + { + ATRACE_NAME("Programming_HWCOMPOSER"); + for (auto compositionInfo : getBE().mCompositionInfo) { + ALOGV("[SF] hwcLayer=%p(%lu), compositionType=%d", + static_cast(*compositionInfo.hwc.hwcLayer), + compositionInfo.hwc.hwcLayer.use_count(), compositionInfo.compositionType); - layer->setPerFrameData(displayDevice); - } + switch (compositionInfo.compositionType) + { + case HWC2::Composition::Invalid: + break; - if (hasWideColorDisplay) { - ColorMode newColorMode; - android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB; + case HWC2::Composition::Client: + break; - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace, - displayDevice->getHdrSupport()); - ALOGV("layer: %s, dataspace: %s (%#x), newDataSpace: %s (%#x)", - layer->getName().string(), dataspaceDetails(layer->getDataSpace()).c_str(), - layer->getDataSpace(), dataspaceDetails(newDataSpace).c_str(), newDataSpace); - } - newColorMode = pickColorMode(newDataSpace); + case HWC2::Composition::SolidColor: + break; - setActiveColorModeInternal(displayDevice, newColorMode); - } - } + case HWC2::Composition::Cursor: + break; - mPreviousColorMatrix = colorMatrix; + case HWC2::Composition::Sideband: + break; - for (size_t dpy = 0; dpy < mDisplays.size(); dpy++) { - sp displayDevice(mDisplays[dpy]); - const auto hwcId = displayDevice->getHwcDisplayId(); - if (hwcId >= 0) { - const Vector>& currentLayers( - displayDevice->getVisibleLayersSortedByZ()); - for (auto& layer : currentLayers) { - layer->configureHwcLayer(displayDevice); + case HWC2::Composition::Device: + configureDeviceComposition(compositionInfo); + break; } } + getBE().mCompositionInfo.clear(); } for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c7ffea7327..f1ab81b434 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -201,6 +201,8 @@ public: // use to differentiate callbacks from different hardware composer // instances. Each hardware composer instance gets a different sequence id. int32_t mComposerSequenceId; + + std::vector mCompositionInfo; }; @@ -631,6 +633,7 @@ private: mat4 computeSaturationMatrix() const; + void calculateWorkingSet(); void setUpHWComposer(); void doComposition(); void doDebugFlashRegions(); @@ -737,6 +740,9 @@ private: // access must be protected by mInvalidateLock volatile int32_t mRepaintEverything; + // helper methods + void configureDeviceComposition(const CompositionInfo& compositionInfo) const; + // constant members (no synchronization needed for access) nsecs_t mBootTime; bool mGpuToCpuSupported; -- cgit v1.2.3-59-g8ed1b From cfb187b458858013453019f62c8cbf29a0a8d623 Mon Sep 17 00:00:00 2001 From: rongliu Date: Wed, 14 Mar 2018 12:26:23 -0700 Subject: Manual merge of ag/3738015 because of conflicts. Conflicts are in layers.proto, LayerProtoParser.h and LayerProtoPraser.cpp as master has more fields in layer proto than pi-dev. Original cl: Pass correct window type and app id to hw composer. 1. Set -1 as default value for window type and app id. 2. When send layer information to hal, layers inherit type and app id from parent node when parent node has valid type/appId. 3. Add window type and app id to SurfaceFlinger dumpsys. Bug: 74622357 Test: Manual test. Several things verified: 1. Android settings layer, status bar layer, nav bar layer have valid window type and appId when start android settings. 2. Layers without buffer have window type -1 and app id -1. 3. When send layers to hal, Chrome SurfaceView layer inherit type and app id from its parent (MainActivity layer). Change-Id: I8d6ad274ca18b61d1bbf6b28f7def5160b55b1e7 --- libs/gui/ISurfaceComposerClient.cpp | 4 ++-- libs/gui/SurfaceComposerClient.cpp | 8 ++++---- libs/gui/include/gui/ISurfaceComposerClient.h | 4 ++-- libs/gui/include/gui/SurfaceComposerClient.h | 8 ++++---- services/surfaceflinger/Client.cpp | 8 ++++---- services/surfaceflinger/Client.h | 2 +- services/surfaceflinger/Layer.cpp | 10 +++++++--- services/surfaceflinger/Layer.h | 6 +++--- services/surfaceflinger/SurfaceFlinger.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.h | 2 +- services/surfaceflinger/layerproto/LayerProtoParser.cpp | 5 ++++- .../layerproto/include/layerproto/LayerProtoParser.h | 2 ++ services/surfaceflinger/layerproto/layers.proto | 2 ++ 13 files changed, 37 insertions(+), 26 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index 679f44b57b..a6890eeb19 100644 --- a/libs/gui/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp @@ -47,8 +47,8 @@ public: ~BpSurfaceComposerClient() override; status_t createSurface(const String8& name, uint32_t width, uint32_t height, PixelFormat format, - uint32_t flags, const sp& parent, uint32_t windowType, - uint32_t ownerUid, sp* handle, + uint32_t flags, const sp& parent, int32_t windowType, + int32_t ownerUid, sp* handle, sp* gbp) override { return callRemote(Tag::CREATE_SURFACE, name, width, height, diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 38f0eb7422..3cf49d6723 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -609,8 +609,8 @@ sp SurfaceComposerClient::createSurface( PixelFormat format, uint32_t flags, SurfaceControl* parent, - uint32_t windowType, - uint32_t ownerUid) + int32_t windowType, + int32_t ownerUid) { sp s; createSurfaceChecked(name, w, h, format, &s, flags, parent, windowType, ownerUid); @@ -625,8 +625,8 @@ status_t SurfaceComposerClient::createSurfaceChecked( sp* outSurface, uint32_t flags, SurfaceControl* parent, - uint32_t windowType, - uint32_t ownerUid) + int32_t windowType, + int32_t ownerUid) { sp sur; status_t err = NO_ERROR; diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h index d5bbef25f8..8dfc99a4b7 100644 --- a/libs/gui/include/gui/ISurfaceComposerClient.h +++ b/libs/gui/include/gui/ISurfaceComposerClient.h @@ -49,8 +49,8 @@ public: * Requires ACCESS_SURFACE_FLINGER permission */ virtual status_t createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format, - uint32_t flags, const sp& parent, uint32_t windowType, - uint32_t ownerUid, sp* handle, + uint32_t flags, const sp& parent, int32_t windowType, + int32_t ownerUid, sp* handle, sp* gbp) = 0; /* diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 5ce20adb89..b45ce4f86c 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -111,8 +111,8 @@ public: PixelFormat format, // pixel-format desired uint32_t flags = 0, // usage flags SurfaceControl* parent = nullptr, // parent - uint32_t windowType = 0, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.) - uint32_t ownerUid = 0 // UID of the task + int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.) + int32_t ownerUid = -1 // UID of the task ); status_t createSurfaceChecked( @@ -123,8 +123,8 @@ public: sp* outSurface, uint32_t flags = 0, // usage flags SurfaceControl* parent = nullptr, // parent - uint32_t windowType = 0, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.) - uint32_t ownerUid = 0 // UID of the task + int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.) + int32_t ownerUid = -1 // UID of the task ); //! Create a virtual display diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index 0c9f0e21e1..c90024b863 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -143,7 +143,7 @@ status_t Client::onTransact( status_t Client::createSurface( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - const sp& parentHandle, uint32_t windowType, uint32_t ownerUid, + const sp& parentHandle, int32_t windowType, int32_t ownerUid, sp* handle, sp* gbp) { @@ -180,13 +180,13 @@ status_t Client::createSurface( PixelFormat format; uint32_t flags; sp* parent; - uint32_t windowType; - uint32_t ownerUid; + int32_t windowType; + int32_t ownerUid; public: MessageCreateLayer(SurfaceFlinger* flinger, const String8& name, Client* client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - sp* handle, uint32_t windowType, uint32_t ownerUid, + sp* handle, int32_t windowType, int32_t ownerUid, sp* gbp, sp* parent) : flinger(flinger), client(client), diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h index 2aab28f37d..c7df9f780f 100644 --- a/services/surfaceflinger/Client.h +++ b/services/surfaceflinger/Client.h @@ -58,7 +58,7 @@ private: virtual status_t createSurface( const String8& name, uint32_t w, uint32_t h,PixelFormat format, uint32_t flags, - const sp& parent, uint32_t windowType, uint32_t ownerUid, + const sp& parent, int32_t windowType, int32_t ownerUid, sp* handle, sp* gbp); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index b072213102..c520f54c36 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -555,8 +555,10 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z sp 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; + } } getBE().compositionInfo.hwc.type = type; @@ -1378,7 +1380,7 @@ bool Layer::setOverrideScalingMode(int32_t scalingMode) { return true; } -void Layer::setInfo(uint32_t type, uint32_t appId) { +void Layer::setInfo(int32_t type, int32_t appId) { mCurrentState.appId = appId; mCurrentState.type = type; mCurrentState.modified = true; @@ -1983,6 +1985,8 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) 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) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 87f9489fa2..029f8acf1e 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -146,8 +146,8 @@ public: Region requestedTransparentRegion; android_dataspace dataSpace; - uint32_t appId; - uint32_t type; + int32_t appId; + int32_t type; // If non-null, a Surface this Surface's Z-order is interpreted relative to. wp zOrderRelativeOf; @@ -228,7 +228,7 @@ public: void deferTransactionUntil(const sp& barrierHandle, uint64_t frameNumber); void deferTransactionUntil(const sp& barrierLayer, uint64_t frameNumber); bool setOverrideScalingMode(int32_t overrideScalingMode); - void setInfo(uint32_t type, uint32_t appId); + void setInfo(int32_t type, int32_t appId); bool reparentChildren(const sp& layer); void reparentChildrenForDrawing(const sp& layer); bool reparent(const sp& newParentHandle); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 4d9643c5ae..4ea7beec9e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3353,7 +3353,7 @@ status_t SurfaceFlinger::createLayer( const String8& name, const sp& client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - uint32_t windowType, uint32_t ownerUid, sp* handle, + int32_t windowType, int32_t ownerUid, sp* handle, sp* gbp, sp* parent) { if (int32_t(w|h) < 0) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c7ffea7327..3b807569b4 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -491,7 +491,7 @@ private: */ status_t createLayer(const String8& name, const sp& client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - uint32_t windowType, uint32_t ownerUid, sp* handle, + int32_t windowType, int32_t ownerUid, sp* handle, sp* gbp, sp* parent); status_t createBufferLayer(const sp& client, const String8& name, diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index 7483abde45..e4545e4494 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -118,6 +118,8 @@ LayerProtoParser::Layer* LayerProtoParser::generateLayer(const LayerProto& layer layer->hwcFrame = generateRect(layerProto.hwc_frame()); layer->hwcCrop = generateFloatRect(layerProto.hwc_crop()); layer->hwcTransform = layerProto.hwc_transform(); + layer->windowType = layerProto.window_type(); + layer->appId = layerProto.app_id(); return layer; } @@ -309,7 +311,8 @@ std::string LayerProtoParser::Layer::to_string() const { StringAppendF(&result, " zOrderRelativeOf=%s\n", zOrderRelativeOf == nullptr ? "none" : zOrderRelativeOf->name.c_str()); StringAppendF(&result, " activeBuffer=%s,", activeBuffer.to_string().c_str()); - StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d", queuedFrames, refreshPending); + StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d,", queuedFrames, refreshPending); + StringAppendF(&result, " windowType=%d, appId=%d", windowType, appId); return result; } diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index 474727567c..44663263c2 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -109,6 +109,8 @@ public: LayerProtoParser::Rect hwcFrame; LayerProtoParser::FloatRect hwcCrop; int32_t hwcTransform; + int32_t windowType; + int32_t appId; std::string to_string() const; }; diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index e232f055fc..6675aae797 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -71,6 +71,8 @@ message LayerProto { optional FloatRectProto hwc_crop = 31; // The layer's composer backend transform optional int32 hwc_transform = 32; + optional int32 window_type = 33; + optional int32 app_id = 34; } message PositionProto { -- cgit v1.2.3-59-g8ed1b From 30505fb0e0f71b88eeed618200c35f9518144060 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Mon, 26 Mar 2018 16:20:31 -0700 Subject: surfacefligner: revert recent BE/FE split changes This reverts the following changes: "SF: Restructure message refresh" "SF: Add sideband stream setup to setUpHwComposer" "SF: Support SolidColor layers in setUpHwComposer" "SF: Move config of HWComposer to setupHwComposer" "SF: Use CompositionInfo to program HWComposer" Bug: 76421986 Bug: 76426897 Bug: 76432611 Test: manual and CTS Change-Id: Ia0c5edaa3a077ba148c8880bee740381fd72f2ca --- services/surfaceflinger/BufferLayer.cpp | 77 ++++-- services/surfaceflinger/ColorLayer.cpp | 32 ++- services/surfaceflinger/Layer.cpp | 92 +++++-- services/surfaceflinger/LayerBE.h | 3 - services/surfaceflinger/SurfaceFlinger.cpp | 373 ++++++++--------------------- services/surfaceflinger/SurfaceFlinger.h | 26 +- 6 files changed, 261 insertions(+), 342 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 916576af20..7dad780a66 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -593,14 +593,32 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) const auto& viewport = displayDevice->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); auto hwcId = displayDevice->getHwcDisplayId(); + auto& hwcInfo = getBE().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(error)); + visible.dump(LOG_TAG); + } - getBE().compositionInfo.hwc.visibleRegion = visible; - getBE().compositionInfo.hwc.surfaceDamage = surfaceDamageRegion; + 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(error)); + surfaceDamageRegion.dump(LOG_TAG); + } // Sideband layers if (getBE().compositionInfo.hwc.sidebandStream.get()) { setCompositionType(hwcId, HWC2::Composition::Sideband); - getBE().compositionInfo.compositionType = HWC2::Composition::Sideband; + ALOGV("[%s] Requesting Sideband composition", mName.string()); + error = (*hwcLayer)->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle()); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(), + getBE().compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(), + static_cast(error)); + } return; } @@ -613,13 +631,32 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) setCompositionType(hwcId, HWC2::Composition::Device); } - getBE().compositionInfo.hwc.dataspace = mDrawingState.dataSpace; - getBE().compositionInfo.hwc.hdrMetadata = mConsumer->getCurrentHdrMetadata(); + ALOGV("setPerFrameData: dataspace = %d", mDrawingState.dataSpace); + error = (*hwcLayer)->setDataspace(mDrawingState.dataSpace); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mDrawingState.dataSpace, + to_string(error).c_str(), static_cast(error)); + } + + const HdrMetadata& metadata = mConsumer->getCurrentHdrMetadata(); + error = (*hwcLayer)->setHdrMetadata(metadata); + if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) { + ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), + to_string(error).c_str(), static_cast(error)); + } + + uint32_t hwcSlot = 0; + sp hwcBuffer; + getBE().mHwcLayers[hwcId].bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, &hwcSlot, + &hwcBuffer); auto acquireFence = mConsumer->getCurrentFence(); - getBE().compositionInfo.mBufferSlot = mActiveBufferSlot; - getBE().compositionInfo.mBuffer = mActiveBuffer; - getBE().compositionInfo.hwc.fence = acquireFence; + error = (*hwcLayer)->setBuffer(hwcSlot, hwcBuffer, acquireFence); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), + getBE().compositionInfo.mBuffer->handle, to_string(error).c_str(), + static_cast(error)); + } } bool BufferLayer::isOpaque(const Layer::State& s) const { @@ -793,17 +830,27 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT texCoords[2] = vec2(right, 1.0f - bottom); texCoords[3] = vec2(right, 1.0f - top); - getBE().compositionInfo.re.preMultipliedAlpha = mPremultipliedAlpha; - getBE().compositionInfo.re.opaque = isOpaque(s); - getBE().compositionInfo.re.disableTexture = false; - getBE().compositionInfo.re.color = getColor(); - getBE().compositionInfo.hwc.dataspace = mCurrentState.dataSpace; - + //getBE().compositionInfo.re.preMultipliedAlpha = mPremultipliedAlpha; + //getBE().compositionInfo.re.opaque = isOpaque(s); + //getBE().compositionInfo.re.disableTexture = false; + //getBE().compositionInfo.re.color = getColor(); + //getBE().compositionInfo.hwc.dataspace = mCurrentState.dataSpace; + + auto& engine(mFlinger->getRenderEngine()); + engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), false /* disableTexture */, + getColor()); + engine.setSourceDataSpace(mCurrentState.dataSpace); + if (mCurrentState.dataSpace == HAL_DATASPACE_BT2020_ITU_PQ && mConsumer->getCurrentApi() == NATIVE_WINDOW_API_MEDIA && getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102) { - getBE().compositionInfo.re.Y410BT2020 = true; + engine.setSourceY410BT2020(true); } + + engine.drawMesh(getBE().mMesh); + engine.disableBlending(); + + engine.setSourceY410BT2020(false); } uint32_t BufferLayer::getProducerStickyTransform() const { diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 5990a61bc5..71975c8f73 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -77,18 +77,38 @@ void ColorLayer::setPerFrameData(const sp& displayDevice) { const auto& viewport = displayDevice->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); auto hwcId = displayDevice->getHwcDisplayId(); - getBE().compositionInfo.hwc.visibleRegion = visible; - getBE().compositionInfo.hwc.dataspace = mDrawingState.dataSpace; + auto& hwcInfo = getBE().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(error)); + visible.dump(LOG_TAG); + } setCompositionType(hwcId, HWC2::Composition::SolidColor); + error = (*hwcLayer)->setDataspace(mDrawingState.dataSpace); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mDrawingState.dataSpace, + to_string(error).c_str(), static_cast(error)); + } + half4 color = getColor(); - getBE().compositionInfo.hwc.color = { static_cast(std::round(255.0f * color.r)), - static_cast(std::round(255.0f * color.g)), - static_cast(std::round(255.0f * color.b)), 255 }; + error = (*hwcLayer)->setColor({static_cast(std::round(255.0f * color.r)), + static_cast(std::round(255.0f * color.g)), + static_cast(std::round(255.0f * color.b)), 255}); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set color: %s (%d)", mName.string(), to_string(error).c_str(), + static_cast(error)); + } // Clear out the transform, because it doesn't make sense absent a source buffer - getBE().compositionInfo.hwc.transform = HWC2::Transform::None; + 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(error)); + } } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index b86408e572..615270fc50 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -483,9 +483,6 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z const auto hwcId = displayDevice->getHwcDisplayId(); auto& hwcInfo = getBE().mHwcLayers[hwcId]; - // Need to program geometry parts - getBE().compositionInfo.hwc.skipGeometry = false; - // enable this layer hwcInfo.forceClientComposition = false; @@ -493,6 +490,8 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z hwcInfo.forceClientComposition = true; } + auto& hwcLayer = hwcInfo.layer; + // this gives us only the "orientation" component of the transform const State& s(getDrawingState()); auto blendMode = HWC2::BlendMode::None; @@ -500,7 +499,12 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z blendMode = mPremultipliedAlpha ? HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage; } - getBE().compositionInfo.hwc.blendMode = blendMode; + 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(error)); // apply the layer's transform, followed by the display's global transform // here we're guaranteed that the layer's transform preserves rects @@ -543,15 +547,36 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z } const Transform& tr(displayDevice->getTransform()); Rect transformedFrame = tr.transform(frame); - getBE().compositionInfo.hwc.displayFrame = transformedFrame; + 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(error)); + } else { + hwcInfo.displayFrame = transformedFrame; + } FloatRect sourceCrop = computeCrop(displayDevice); - getBE().compositionInfo.hwc.sourceCrop = sourceCrop; + 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(error)); + } else { + hwcInfo.sourceCrop = sourceCrop; + } float alpha = static_cast(getAlpha()); - getBE().compositionInfo.hwc.alpha = alpha; + 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(error)); - getBE().compositionInfo.hwc.z = z; + 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(error)); int type = s.type; int appId = s.appId; @@ -564,8 +589,9 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z } } - getBE().compositionInfo.hwc.type = type; - getBE().compositionInfo.hwc.appId = appId; + error = (*hwcLayer)->setInfo(type, appId); + ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)", mName.string(), + static_cast(error)); /* * Transformations are applied in this order: @@ -608,11 +634,16 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z const uint32_t orientation = transform.getOrientation(); if (orientation & Transform::ROT_INVALID || extremeScaling) { // we can only handle simple transformation - getBE().mHwcLayers[hwcId].compositionType = HWC2::Composition::Client; + hwcInfo.forceClientComposition = true; } else { auto transform = static_cast(orientation); hwcInfo.transform = transform; - getBE().compositionInfo.hwc.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(error)); } } @@ -697,12 +728,26 @@ void Layer::clearWithOpenGL(const RenderArea& renderArea) const { clearWithOpenGL(renderArea, 0, 0, 0, 0); } -void Layer::setCompositionType(int32_t /*hwcId*/, HWC2::Composition type, bool /*callIntoHwc*/) { - if (getBE().compositionInfo.compositionType != type) { - ALOGV("setCompositionType: Changing compositionType from %s to %s", - to_string(getBE().compositionInfo.compositionType).c_str(), - to_string(type).c_str()); - getBE().compositionInfo.compositionType = type; +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 = getBE().mHwcLayers[hwcId]; + auto& hwcLayer = hwcInfo.layer; + ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", (*hwcLayer)->getId(), to_string(type).c_str(), + static_cast(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(error)); + } } } @@ -712,7 +757,11 @@ HWC2::Composition Layer::getCompositionType(int32_t hwcId) const { // have a HWC counterpart, then it will always be Client return HWC2::Composition::Client; } - return getBE().compositionInfo.compositionType; + if (getBE().mHwcLayers.count(hwcId) == 0) { + ALOGE("getCompositionType called with an invalid HWC layer"); + return HWC2::Composition::Invalid; + } + return getBE().mHwcLayers.at(hwcId).compositionType; } void Layer::setClearClientTarget(int32_t hwcId, bool clear) { @@ -1441,11 +1490,12 @@ void Layer::miniDump(String8& result, int32_t hwcId) const { result.appendFormat(" %s\n", name.string()); const Layer::State& layerState(getDrawingState()); + const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(hwcId); result.appendFormat(" %10d | ", layerState.z); result.appendFormat("%10s | ", to_string(getCompositionType(hwcId)).c_str()); - const Rect& frame = getBE().compositionInfo.hwc.displayFrame; + const Rect& frame = hwcInfo.displayFrame; result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom); - const FloatRect& crop = getBE().compositionInfo.hwc.sourceCrop; + 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.append("- - - - - - - - - - - - - - - - - - - - "); diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index fafe165600..854cdd692b 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -19,7 +19,6 @@ #include #include -#include #include #include "SurfaceFlinger.h" @@ -66,7 +65,6 @@ struct CompositionInfo { LayerBE* layer = nullptr; struct { std::shared_ptr hwcLayer; - bool skipGeometry = true; int32_t hwid = -1; sp fence; HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid; @@ -82,7 +80,6 @@ struct CompositionInfo { sp sidebandStream; android_dataspace dataspace; hwc_color_t color; - HdrMetadata hdrMetadata; } hwc; struct { Mesh* mesh; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a21b7eaeee..f709534972 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -674,7 +674,6 @@ void SurfaceFlinger::init() { // set initial conditions (e.g. unblank default device) initializeDisplays(); - ALOGV("Displays initialized"); getBE().mRenderEngine->primeCache(); @@ -1443,13 +1442,7 @@ void SurfaceFlinger::onMessageReceived(int32_t what) { bool refreshNeeded = handleMessageTransaction(); refreshNeeded |= handleMessageInvalidate(); refreshNeeded |= mRepaintEverything; - - preComposition(); - rebuildLayerStacks(); - calculateWorkingSet(); - if (refreshNeeded) { - // Signal a refresh if a transaction modified the window state, // a new buffer was latched, or if HWC has requested a full // repaint @@ -1478,120 +1471,21 @@ bool SurfaceFlinger::handleMessageInvalidate() { return handlePageFlip(); } -void SurfaceFlinger::calculateWorkingSet() { - ATRACE_CALL(); - ALOGV(__FUNCTION__); - - // build the h/w work list - if (CC_UNLIKELY(mGeometryInvalid)) { - mGeometryInvalid = false; - for (size_t dpy=0 ; dpy displayDevice(mDisplays[dpy]); - const auto hwcId = displayDevice->getHwcDisplayId(); - if (hwcId >= 0) { - const Vector>& currentLayers( - displayDevice->getVisibleLayersSortedByZ()); - for (size_t i = 0; i < currentLayers.size(); i++) { - const auto& layer = currentLayers[i]; - - if (!layer->hasHwcLayer(hwcId)) { - if (!layer->createHwcLayer(getBE().mHwc.get(), hwcId)) { - layer->forceClientComposition(hwcId); - continue; - } - } - - layer->setGeometry(displayDevice, i); - if (mDebugDisableHWC || mDebugRegion) { - layer->forceClientComposition(hwcId); - } - } - } - } - } - mat4 colorMatrix = mColorMatrix * computeSaturationMatrix() * mDaltonizer(); - - // Set the per-frame data - for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { - auto& displayDevice = mDisplays[displayId]; - const auto hwcId = displayDevice->getHwcDisplayId(); - - if (hwcId < 0) { - continue; - } - if (colorMatrix != mPreviousColorMatrix) { - status_t result = getBE().mHwc->setColorTransform(hwcId, colorMatrix); - ALOGE_IF(result != NO_ERROR, "Failed to set color transform on " - "display %zd: %d", displayId, result); - } - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - if ((layer->getDataSpace() == HAL_DATASPACE_BT2020_PQ || - layer->getDataSpace() == HAL_DATASPACE_BT2020_ITU_PQ) && - !displayDevice->getHdrSupport()) { - layer->forceClientComposition(hwcId); - } - - if (layer->getForceClientComposition(hwcId)) { - ALOGV("[%s] Requesting Client composition", layer->getName().string()); - layer->setCompositionType(hwcId, HWC2::Composition::Client); - continue; - } - - layer->setPerFrameData(displayDevice); - } - - if (hasWideColorDisplay) { - ColorMode newColorMode; - android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB; - - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace, - displayDevice->getHdrSupport()); - ALOGV("layer: %s, dataspace: %s (%#x), newDataSpace: %s (%#x)", - layer->getName().string(), dataspaceDetails(layer->getDataSpace()).c_str(), - layer->getDataSpace(), dataspaceDetails(newDataSpace).c_str(), newDataSpace); - } - newColorMode = pickColorMode(newDataSpace); - - setActiveColorModeInternal(displayDevice, newColorMode); - } - } - - mPreviousColorMatrix = colorMatrix; - for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { - auto& displayDevice = mDisplays[displayId]; - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - auto hwcId = displayDevice->getHwcDisplayId(); - layer->getBE().compositionInfo.compositionType = layer->getCompositionType(hwcId); - if (!layer->setHwcLayer(hwcId)) { - ALOGV("Need to create HWCLayer for %s", layer->getName().string()); - } - layer->getBE().compositionInfo.hwc.hwid = hwcId; - getBE().mCompositionInfo.push_back(layer->getBE().compositionInfo); - layer->getBE().compositionInfo.hwc.hwcLayer = nullptr; - } - } -} - void SurfaceFlinger::handleMessageRefresh() { ATRACE_CALL(); mRefreshPending = false; + nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC); - - beginFrame(); - for (auto compositionInfo : getBE().mCompositionInfo) { - setUpHWComposer(compositionInfo); - } - prepareFrame(); + preComposition(refreshStartTime); + rebuildLayerStacks(); + setUpHWComposer(); doDebugFlashRegions(); doTracing("handleRefresh"); logLayerStats(); doComposition(); - postComposition(); - - getBE().mCompositionInfo.clear(); + postComposition(refreshStartTime); mPreviousPresentFence = getBE().mHwc->getPresentFence(HWC_DISPLAY_PRIMARY); @@ -1678,14 +1572,14 @@ void SurfaceFlinger::logLayerStats() { } } -void SurfaceFlinger::preComposition() +void SurfaceFlinger::preComposition(nsecs_t refreshStartTime) { ATRACE_CALL(); ALOGV("preComposition"); bool needExtraInvalidate = false; mDrawingState.traverseInZOrder([&](Layer* layer) { - if (layer->onPreComposition(mRefreshStartTime)) { + if (layer->onPreComposition(refreshStartTime)) { needExtraInvalidate = true; } }); @@ -1754,7 +1648,7 @@ void SurfaceFlinger::setCompositorTimingSnapped(nsecs_t vsyncPhase, getBE().mCompositorTiming.presentLatency = snappedCompositeToPresentLatency; } -void SurfaceFlinger::postComposition() +void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) { ATRACE_CALL(); ALOGV("postComposition"); @@ -1786,11 +1680,11 @@ void SurfaceFlinger::postComposition() nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0); nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod(); - // We use the mRefreshStartTime which might be sampled a little later than + // We use the refreshStartTime which might be sampled a little later than // when we started doing work for this frame, but that should be okay // since updateCompositorTiming has snapping logic. updateCompositorTiming( - vsyncPhase, vsyncInterval, mRefreshStartTime, presentFenceTime); + vsyncPhase, vsyncInterval, refreshStartTime, presentFenceTime); CompositorTiming compositorTiming; { std::lock_guard lock(getBE().mCompositorTimingLock); @@ -1888,21 +1782,17 @@ void SurfaceFlinger::rebuildLayerStacks() { if (!drawRegion.isEmpty()) { layersSortedByZ.add(layer); } else { - if (layer->hasHwcLayer(displayDevice->getHwcDisplayId())) { - // Clear out the HWC layer if this layer was - // previously visible, but no longer is - hwcLayerDestroyed = layer->destroyHwcLayer( - displayDevice->getHwcDisplayId()); - } - } - } else { - if (layer->hasHwcLayer(displayDevice->getHwcDisplayId())) { - // WM changes displayDevice->layerStack upon sleep/awake. - // Here we make sure we delete the HWC layers even if - // WM changed their layer stack. + // Clear out the HWC layer if this layer was + // previously visible, but no longer is hwcLayerDestroyed = layer->destroyHwcLayer( displayDevice->getHwcDisplayId()); } + } else { + // WM changes displayDevice->layerStack upon sleep/awake. + // Here we make sure we delete the HWC layers even if + // WM changed their layer stack. + hwcLayerDestroyed = layer->destroyHwcLayer( + displayDevice->getHwcDisplayId()); } // If a layer is not going to get a release fence because @@ -1997,123 +1887,9 @@ android_dataspace SurfaceFlinger::bestTargetDataSpace( return HAL_DATASPACE_V0_SRGB; } -void SurfaceFlinger::configureSidebandComposition(const CompositionInfo& compositionInfo) const -{ - HWC2::Error error; - LOG_ALWAYS_FATAL_IF(compositionInfo.hwc.sidebandStream == nullptr, - "CompositionType is sideband, but sideband stream is nullptr"); - error = (*compositionInfo.hwc.hwcLayer) - ->setSidebandStream(compositionInfo.hwc.sidebandStream->handle()); - if (error != HWC2::Error::None) { - ALOGE("[SF] Failed to set sideband stream %p: %s (%d)", - compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(), - static_cast(error)); - } -} - -void SurfaceFlinger::configureHwcCommonData(const CompositionInfo& compositionInfo) const -{ - HWC2::Error error; - - if (!compositionInfo.hwc.skipGeometry) { - error = (*compositionInfo.hwc.hwcLayer)->setBlendMode(compositionInfo.hwc.blendMode); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set blend mode %s:" - " %s (%d)", - to_string(compositionInfo.hwc.blendMode).c_str(), to_string(error).c_str(), - static_cast(error)); - - error = (*compositionInfo.hwc.hwcLayer)->setDisplayFrame(compositionInfo.hwc.displayFrame); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set the display frame [%d, %d, %d, %d] %s (%d)", - compositionInfo.hwc.displayFrame.left, - compositionInfo.hwc.displayFrame.right, - compositionInfo.hwc.displayFrame.top, - compositionInfo.hwc.displayFrame.bottom, - to_string(error).c_str(), static_cast(error)); - - error = (*compositionInfo.hwc.hwcLayer)->setSourceCrop(compositionInfo.hwc.sourceCrop); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: %s (%d)", - compositionInfo.hwc.sourceCrop.left, - compositionInfo.hwc.sourceCrop.right, - compositionInfo.hwc.sourceCrop.top, - compositionInfo.hwc.sourceCrop.bottom, - to_string(error).c_str(), static_cast(error)); - - error = (*compositionInfo.hwc.hwcLayer)->setPlaneAlpha(compositionInfo.hwc.alpha); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set plane alpha %.3f: " - "%s (%d)", - compositionInfo.hwc.alpha, - to_string(error).c_str(), static_cast(error)); - - - error = (*compositionInfo.hwc.hwcLayer)->setZOrder(compositionInfo.hwc.z); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set Z %u: %s (%d)", - compositionInfo.hwc.z, - to_string(error).c_str(), static_cast(error)); - - error = (*compositionInfo.hwc.hwcLayer) - ->setInfo(compositionInfo.hwc.type, compositionInfo.hwc.appId); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set info (%d)", - static_cast(error)); - - error = (*compositionInfo.hwc.hwcLayer)->setTransform(compositionInfo.hwc.transform); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set transform %s: " - "%s (%d)", - to_string(compositionInfo.hwc.transform).c_str(), to_string(error).c_str(), - static_cast(error)); - } - - error = (*compositionInfo.hwc.hwcLayer)->setCompositionType(compositionInfo.compositionType); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set composition type: %s (%d)", - to_string(error).c_str(), static_cast(error)); - - error = (*compositionInfo.hwc.hwcLayer)->setDataspace(compositionInfo.hwc.dataspace); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set dataspace: %s (%d)", - to_string(error).c_str(), static_cast(error)); - - error = (*compositionInfo.hwc.hwcLayer)->setHdrMetadata(compositionInfo.hwc.hdrMetadata); - ALOGE_IF(error != HWC2::Error::None && error != HWC2::Error::Unsupported, - "[SF] Failed to set hdrMetadata: %s (%d)", - to_string(error).c_str(), static_cast(error)); - - error = (*compositionInfo.hwc.hwcLayer)->setColor(compositionInfo.hwc.color); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set color: %s (%d)", - to_string(error).c_str(), static_cast(error)); - - error = (*compositionInfo.hwc.hwcLayer)->setVisibleRegion(compositionInfo.hwc.visibleRegion); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set visible region: %s (%d)", - to_string(error).c_str(), static_cast(error)); -} - -void SurfaceFlinger::configureDeviceComposition(const CompositionInfo& compositionInfo) const -{ - HWC2::Error error; - - error = (*compositionInfo.hwc.hwcLayer)->setSurfaceDamage(compositionInfo.hwc.surfaceDamage); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set surface damage: %s (%d)", - to_string(error).c_str(), static_cast(error)); - - error = (*compositionInfo.hwc.hwcLayer)->setBuffer(compositionInfo.mBufferSlot, - compositionInfo.mBuffer, compositionInfo.hwc.fence); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set buffer: %s (%d)", - to_string(error).c_str(), static_cast(error)); -} - -void SurfaceFlinger::beginFrame() -{ - mRefreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC); +void SurfaceFlinger::setUpHWComposer() { + ATRACE_CALL(); + ALOGV("setUpHWComposer"); for (size_t dpy=0 ; dpygetDirtyRegion(false).isEmpty(); @@ -2143,45 +1919,94 @@ void SurfaceFlinger::beginFrame() mDisplays[dpy]->lastCompositionHadVisibleLayers = !empty; } } -} -void SurfaceFlinger::prepareFrame() -{ + // build the h/w work list + if (CC_UNLIKELY(mGeometryInvalid)) { + mGeometryInvalid = false; + for (size_t dpy=0 ; dpy displayDevice(mDisplays[dpy]); + const auto hwcId = displayDevice->getHwcDisplayId(); + if (hwcId >= 0) { + const Vector>& currentLayers( + displayDevice->getVisibleLayersSortedByZ()); + for (size_t i = 0; i < currentLayers.size(); i++) { + const auto& layer = currentLayers[i]; + if (!layer->hasHwcLayer(hwcId)) { + if (!layer->createHwcLayer(getBE().mHwc.get(), hwcId)) { + layer->forceClientComposition(hwcId); + continue; + } + } + + layer->setGeometry(displayDevice, i); + if (mDebugDisableHWC || mDebugRegion) { + layer->forceClientComposition(hwcId); + } + } + } + } + } + + + mat4 colorMatrix = mColorMatrix * computeSaturationMatrix() * mDaltonizer(); + + // Set the per-frame data for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { auto& displayDevice = mDisplays[displayId]; - if (!displayDevice->isDisplayOn()) { + const auto hwcId = displayDevice->getHwcDisplayId(); + + if (hwcId < 0) { continue; } + if (colorMatrix != mPreviousColorMatrix) { + status_t result = getBE().mHwc->setColorTransform(hwcId, colorMatrix); + ALOGE_IF(result != NO_ERROR, "Failed to set color transform on " + "display %zd: %d", displayId, result); + } + for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { + if ((layer->getDataSpace() == HAL_DATASPACE_BT2020_PQ || + layer->getDataSpace() == HAL_DATASPACE_BT2020_ITU_PQ) && + !displayDevice->getHdrSupport()) { + layer->forceClientComposition(hwcId); + } - status_t result = displayDevice->prepareFrame(*getBE().mHwc); - ALOGE_IF(result != NO_ERROR, "prepareFrame for display %zd failed:" - " %d (%s)", displayId, result, strerror(-result)); - } -} + if (layer->getForceClientComposition(hwcId)) { + ALOGV("[%s] Requesting Client composition", layer->getName().string()); + layer->setCompositionType(hwcId, HWC2::Composition::Client); + continue; + } -void SurfaceFlinger::setUpHWComposer(const CompositionInfo& compositionInfo) { - ATRACE_CALL(); - ALOGV("setUpHWComposer"); + layer->setPerFrameData(displayDevice); + } - switch (compositionInfo.compositionType) - { - case HWC2::Composition::Invalid: - case HWC2::Composition::Client: - case HWC2::Composition::Cursor: - break; + if (hasWideColorDisplay) { + ColorMode newColorMode; + android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB; - case HWC2::Composition::Sideband: - configureSidebandComposition(compositionInfo); - break; + for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { + newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace, + displayDevice->getHdrSupport()); + ALOGV("layer: %s, dataspace: %s (%#x), newDataSpace: %s (%#x)", + layer->getName().string(), dataspaceDetails(layer->getDataSpace()).c_str(), + layer->getDataSpace(), dataspaceDetails(newDataSpace).c_str(), newDataSpace); + } + newColorMode = pickColorMode(newDataSpace); - case HWC2::Composition::SolidColor: - configureHwcCommonData(compositionInfo); - break; + setActiveColorModeInternal(displayDevice, newColorMode); + } + } - case HWC2::Composition::Device: - configureHwcCommonData(compositionInfo); - configureDeviceComposition(compositionInfo); - break; + mPreviousColorMatrix = colorMatrix; + + for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { + auto& displayDevice = mDisplays[displayId]; + if (!displayDevice->isDisplayOn()) { + continue; + } + + status_t result = displayDevice->prepareFrame(*getBE().mHwc); + ALOGE_IF(result != NO_ERROR, "prepareFrame for display %zd failed:" + " %d (%s)", displayId, result, strerror(-result)); } } @@ -3002,7 +2827,6 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev } bool hasClientComposition = getBE().mHwc->hasClientComposition(hwcId); - ATRACE_INT("hasClientComposition", hasClientComposition); if (hasClientComposition) { ALOGV("hasClientComposition"); @@ -5113,6 +4937,7 @@ void SurfaceFlinger::traverseLayersInDisplay(const sp& hw, }; // namespace android + #if defined(__gl_h_) #error "don't include gl/gl.h in this file" #endif diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 77efa540c0..99bbb13211 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -214,8 +214,6 @@ public: // use to differentiate callbacks from different hardware composer // instances. Each hardware composer instance gets a different sequence id. int32_t mComposerSequenceId; - - std::vector mCompositionInfo; }; @@ -628,8 +626,8 @@ private: void computeVisibleRegions(const sp& displayDevice, Region& dirtyRegion, Region& opaqueRegion); - void preComposition(); - void postComposition(); + void preComposition(nsecs_t refreshStartTime); + void postComposition(nsecs_t refreshStartTime); void updateCompositorTiming( nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime, std::shared_ptr& presentFenceTime); @@ -646,19 +644,7 @@ private: mat4 computeSaturationMatrix() const; - void calculateWorkingSet(); - /* - * beginFrame - This function handles any pre-frame processing that needs to be - * prior to any CompositionInfo handling and is not dependent on data in - * CompositionInfo - */ - void beginFrame(); - /* prepareFrame - This function will call into the DisplayDevice to prepare a - * frame after CompositionInfo has been programmed. This provides a mechanism - * to prepare the hardware composer - */ - void prepareFrame(); - void setUpHWComposer(const CompositionInfo& compositionInfo); + void setUpHWComposer(); void doComposition(); void doDebugFlashRegions(); void doTracing(const char* where); @@ -768,11 +754,6 @@ private: // access must be protected by mInvalidateLock volatile int32_t mRepaintEverything; - // helper methods - void configureHwcCommonData(const CompositionInfo& compositionInfo) const; - void configureDeviceComposition(const CompositionInfo& compositionInfo) const; - void configureSidebandComposition(const CompositionInfo& compositionInfo) const; - // constant members (no synchronization needed for access) nsecs_t mBootTime; bool mGpuToCpuSupported; @@ -840,7 +821,6 @@ private: Mutex mHWVsyncLock; bool mPrimaryHWVsyncEnabled; bool mHWVsyncAvailable; - nsecs_t mRefreshStartTime; std::atomic mRefreshPending{false}; -- cgit v1.2.3-59-g8ed1b From 60d1a19324b2c0d5cee01f5467fd708aaef7e24f Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Wed, 7 Mar 2018 14:52:28 -0800 Subject: Implement Display Layer Stats V0.1 Try to collect data for analyzing how many display controller layers we need and what we use them for. This change will collect additional data from per frame point of view. Test: adb shell dumpsys SurfaceFlinger --enable-layer-stats Test: adb shell dumpsys SurfaceFlinger --disable-layer-stats Test: adb shell dumpsys SurfaceFlinger --clear-layer-stats Test: adb shell dumpsys SurfaceFlinger --dump-layer-stats Bug: b/75953772 Change-Id: Ib48777df7e1fed637be7eb1aefbdf1808d1daccd --- libs/ui/DebugUtils.cpp | 27 ++++++ libs/ui/include/ui/DebugUtils.h | 1 + services/surfaceflinger/DisplayDevice.cpp | 11 +++ services/surfaceflinger/DisplayDevice.h | 6 ++ services/surfaceflinger/Layer.cpp | 11 +++ services/surfaceflinger/LayerStats.cpp | 95 +++++++++++++++++----- services/surfaceflinger/LayerStats.h | 19 +++-- services/surfaceflinger/SurfaceFlinger.cpp | 11 ++- .../surfaceflinger/layerproto/LayerProtoParser.cpp | 9 +- .../include/layerproto/LayerProtoParser.h | 5 ++ services/surfaceflinger/layerproto/layers.proto | 7 ++ 11 files changed, 170 insertions(+), 32 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp index d7e191db89..d5654ccfe3 100644 --- a/libs/ui/DebugUtils.cpp +++ b/libs/ui/DebugUtils.cpp @@ -234,6 +234,33 @@ std::string decodeColorMode(ColorMode colorMode) { return android::base::StringPrintf("Unknown color mode %d", colorMode); } +std::string decodeColorTransform(android_color_transform colorTransform) { + switch (colorTransform) { + case HAL_COLOR_TRANSFORM_IDENTITY: + return std::string("Identity"); + + case HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX: + return std::string("Arbitrary matrix"); + + case HAL_COLOR_TRANSFORM_VALUE_INVERSE: + return std::string("Inverse value"); + + case HAL_COLOR_TRANSFORM_GRAYSCALE: + return std::string("Grayscale"); + + case HAL_COLOR_TRANSFORM_CORRECT_PROTANOPIA: + return std::string("Correct protanopia"); + + case HAL_COLOR_TRANSFORM_CORRECT_DEUTERANOPIA: + return std::string("Correct deuteranopia"); + + case HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA: + return std::string("Correct tritanopia"); + } + + return android::base::StringPrintf("Unknown color transform %d", colorTransform); +} + // Converts a PixelFormat to a human-readable string. Max 11 chars. // (Could use a table of prefab String8 objects.) std::string decodePixelFormat(android::PixelFormat format) { diff --git a/libs/ui/include/ui/DebugUtils.h b/libs/ui/include/ui/DebugUtils.h index 33701070a9..769009317f 100644 --- a/libs/ui/include/ui/DebugUtils.h +++ b/libs/ui/include/ui/DebugUtils.h @@ -30,5 +30,6 @@ std::string decodeTransfer(android_dataspace dataspace); std::string decodeRange(android_dataspace dataspace); std::string dataspaceDetails(android_dataspace dataspace); std::string decodeColorMode(android::ColorMode colormode); +std::string decodeColorTransform(android_color_transform colorTransform); std::string decodePixelFormat(android::PixelFormat format); std::string to_string(const android::Rect& rect); diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index fe0b30ba35..e4161bbdb9 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -98,6 +98,7 @@ DisplayDevice::DisplayDevice( mPowerMode(initialPowerMode), mActiveConfig(0), mActiveColorMode(ColorMode::NATIVE), + mColorTransform(HAL_COLOR_TRANSFORM_IDENTITY), mDisplayHasWideColor(supportWideColor), mDisplayHasHdr(supportHdr) { @@ -268,6 +269,16 @@ ColorMode DisplayDevice::getActiveColorMode() const { return mActiveColorMode; } +void DisplayDevice::setColorTransform(const mat4& transform) { + const bool isIdentity = (transform == mat4()); + mColorTransform = + isIdentity ? HAL_COLOR_TRANSFORM_IDENTITY : HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX; +} + +android_color_transform_t DisplayDevice::getColorTransform() const { + return mColorTransform; +} + void DisplayDevice::setCompositionDataSpace(android_dataspace dataspace) { ANativeWindow* const window = mNativeWindow.get(); native_window_set_buffers_data_space(window, dataspace); diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index fbb0d462f3..c1ef2e890a 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -21,6 +21,8 @@ #include +#include + #include #include @@ -163,6 +165,8 @@ public: ColorMode getActiveColorMode() const; void setActiveColorMode(ColorMode mode); + android_color_transform_t getColorTransform() const; + void setColorTransform(const mat4& transform); void setCompositionDataSpace(android_dataspace dataspace); /* ------------------------------------------------------------------------ @@ -237,6 +241,8 @@ private: int mActiveConfig; // current active color mode ColorMode mActiveColorMode; + // Current color transform + android_color_transform_t mColorTransform; // Need to know if display is wide-color capable or not. // Initialized by SurfaceFlinger when the DisplayDevice is created. diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 3dc8cae476..43bef60504 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -42,6 +42,7 @@ #include #include +#include "BufferLayer.h" #include "Colorizer.h" #include "DisplayDevice.h" #include "Layer.h" @@ -1935,6 +1936,16 @@ void Layer::writeToProto(LayerProto* layerInfo, int32_t hwcId) { const int32_t transform = static_cast(hwcInfo.transform); layerInfo->set_hwc_transform(transform); + + const int32_t compositionType = static_cast(hwcInfo.compositionType); + layerInfo->set_hwc_composition_type(compositionType); + + if (std::strcmp(getTypeId(), "BufferLayer") == 0 && + static_cast(this)->isProtected()) { + layerInfo->set_is_protected(true); + } else { + layerInfo->set_is_protected(false); + } } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/LayerStats.cpp b/services/surfaceflinger/LayerStats.cpp index ad1043f653..38ea6edfc5 100644 --- a/services/surfaceflinger/LayerStats.cpp +++ b/services/surfaceflinger/LayerStats.cpp @@ -19,6 +19,7 @@ #include "LayerStats.h" #include "DisplayHardware/HWComposer.h" +#include "ui/DebugUtils.h" #include #include @@ -31,7 +32,7 @@ void LayerStats::enable() { ATRACE_CALL(); std::lock_guard lock(mMutex); if (mEnabled) return; - mLayerStatsMap.clear(); + mLayerShapeStatsMap.clear(); mEnabled = true; ALOGD("Logging enabled"); } @@ -47,7 +48,7 @@ void LayerStats::disable() { void LayerStats::clear() { ATRACE_CALL(); std::lock_guard lock(mMutex); - mLayerStatsMap.clear(); + mLayerShapeStatsMap.clear(); ALOGD("Cleared current layer stats"); } @@ -57,42 +58,69 @@ bool LayerStats::isEnabled() { void LayerStats::traverseLayerTreeStatsLocked( std::vector> layerTree, - const LayerProtoParser::LayerGlobal* layerGlobal) { + const LayerProtoParser::LayerGlobal* layerGlobal, std::vector& layerShapeVec) { for (std::unique_ptr& layer : layerTree) { if (!layer) continue; - traverseLayerTreeStatsLocked(std::move(layer->children), layerGlobal); - std::string key = - base::StringPrintf("%s,%s,%s,%s,%s,%s,%s,%s,%s", - destinationLocation(layer->hwcFrame.left, - layerGlobal->resolution[0], true), - destinationLocation(layer->hwcFrame.top, - layerGlobal->resolution[1], false), - destinationSize(layer->hwcFrame.right - layer->hwcFrame.left, - layerGlobal->resolution[0], true), - destinationSize(layer->hwcFrame.bottom - layer->hwcFrame.top, - layerGlobal->resolution[1], false), - layer->type.c_str(), scaleRatioWH(layer.get()).c_str(), - layerTransform(layer->hwcTransform), layer->pixelFormat.c_str(), - layer->dataspace.c_str()); - mLayerStatsMap[key]++; + traverseLayerTreeStatsLocked(std::move(layer->children), layerGlobal, layerShapeVec); + std::string key = ""; + base::StringAppendF(&key, ",%s", layer->type.c_str()); + base::StringAppendF(&key, ",%s", layerCompositionType(layer->hwcCompositionType)); + base::StringAppendF(&key, ",%d", layer->isProtected); + base::StringAppendF(&key, ",%s", layerTransform(layer->hwcTransform)); + base::StringAppendF(&key, ",%s", layerPixelFormat(layer->activeBuffer.format)); + base::StringAppendF(&key, ",%s", layer->dataspace.c_str()); + base::StringAppendF(&key, ",%s", + destinationLocation(layer->hwcFrame.left, layerGlobal->resolution[0], + true)); + base::StringAppendF(&key, ",%s", + destinationLocation(layer->hwcFrame.top, layerGlobal->resolution[1], + false)); + base::StringAppendF(&key, ",%s", + destinationSize(layer->hwcFrame.right - layer->hwcFrame.left, + layerGlobal->resolution[0], true)); + base::StringAppendF(&key, ",%s", + destinationSize(layer->hwcFrame.bottom - layer->hwcFrame.top, + layerGlobal->resolution[1], false)); + base::StringAppendF(&key, ",%s", scaleRatioWH(layer.get()).c_str()); + base::StringAppendF(&key, ",%s", alpha(static_cast(layer->color.a))); + + layerShapeVec.push_back(key); + ALOGV("%s", key.c_str()); } } void LayerStats::logLayerStats(const LayersProto& layersProto) { ATRACE_CALL(); + ALOGV("Logging"); auto layerGlobal = LayerProtoParser::generateLayerGlobalInfo(layersProto); auto layerTree = LayerProtoParser::generateLayerTree(layersProto); + std::vector layerShapeVec; + std::lock_guard lock(mMutex); - traverseLayerTreeStatsLocked(std::move(layerTree), &layerGlobal); + traverseLayerTreeStatsLocked(std::move(layerTree), &layerGlobal, layerShapeVec); + + std::string layerShapeKey = + base::StringPrintf("%d,%s,%s,%s", static_cast(layerShapeVec.size()), + layerGlobal.colorMode.c_str(), layerGlobal.colorTransform.c_str(), + layerTransform(layerGlobal.globalTransform)); + ALOGV("%s", layerShapeKey.c_str()); + + std::sort(layerShapeVec.begin(), layerShapeVec.end(), std::greater()); + for (auto const& s : layerShapeVec) { + layerShapeKey += s; + } + + mLayerShapeStatsMap[layerShapeKey]++; } void LayerStats::dump(String8& result) { ATRACE_CALL(); ALOGD("Dumping"); - result.append("Count,DstPosX,DstPosY,DstWidth,DstHeight,LayerType,WScale,HScale,"); - result.append("Transform,PixelFormat,Dataspace\n"); std::lock_guard lock(mMutex); - for (auto& u : mLayerStatsMap) { + result.append("Frequency,LayerCount,ColorMode,ColorTransform,Orientation\n"); + result.append("LayerType,CompositionType,IsProtected,Transform,PixelFormat,Dataspace,"); + result.append("DstX,DstY,DstWidth,DstHeight,WScale,HScale,Alpha\n"); + for (auto& u : mLayerShapeStatsMap) { result.appendFormat("%u,%s\n", u.second, u.first.c_str()); } } @@ -129,6 +157,14 @@ const char* LayerStats::layerTransform(int32_t transform) { return getTransformName(static_cast(transform)); } +const char* LayerStats::layerCompositionType(int32_t compositionType) { + return getCompositionName(static_cast(compositionType)); +} + +const char* LayerStats::layerPixelFormat(int32_t pixelFormat) { + return decodePixelFormat(pixelFormat).c_str(); +} + std::string LayerStats::scaleRatioWH(const LayerProtoParser::Layer* layer) { if (!layer->type.compare("ColorLayer")) return "N/A,N/A"; std::string ret = ""; @@ -166,6 +202,21 @@ const char* LayerStats::scaleRatio(int32_t destinationScale, int32_t sourceScale return ">=16"; } +const char* LayerStats::alpha(float a) { + if (a == 1.0f) return "1.0"; + if (a > 0.9f) return "0.99"; + if (a > 0.8f) return "0.9"; + if (a > 0.7f) return "0.8"; + if (a > 0.6f) return "0.7"; + if (a > 0.5f) return "0.6"; + if (a > 0.4f) return "0.5"; + if (a > 0.3f) return "0.4"; + if (a > 0.2f) return "0.3"; + if (a > 0.1f) return "0.2"; + if (a > 0.0f) return "0.1"; + return "0.0"; +} + bool LayerStats::isRotated(int32_t transform) { return transform & HWC_TRANSFORM_ROT_90; } diff --git a/services/surfaceflinger/LayerStats.h b/services/surfaceflinger/LayerStats.h index 95227250f9..7871fc6602 100644 --- a/services/surfaceflinger/LayerStats.h +++ b/services/surfaceflinger/LayerStats.h @@ -38,18 +38,25 @@ public: private: // Traverse layer tree to get all visible layers' stats void traverseLayerTreeStatsLocked( - std::vector> layerTree, - const LayerProtoParser::LayerGlobal* layerGlobal); + std::vector> layerTree, + const LayerProtoParser::LayerGlobal* layerGlobal, + std::vector& layerShapeVec); // Convert layer's top-left position into 8x8 percentage of the display static const char* destinationLocation(int32_t location, int32_t range, bool isHorizontal); // Convert layer's size into 8x8 percentage of the display static const char* destinationSize(int32_t size, int32_t range, bool isWidth); // Return the name of the transform static const char* layerTransform(int32_t transform); + // Return the name of the composition type + static const char* layerCompositionType(int32_t compositionType); + // Return the name of the pixel format + static const char* layerPixelFormat(int32_t pixelFormat); // Calculate scale ratios of layer's width/height with rotation information static std::string scaleRatioWH(const LayerProtoParser::Layer* layer); // Calculate scale ratio from source to destination and convert to string static const char* scaleRatio(int32_t destinationScale, int32_t sourceScale); + // Bucket the alpha into designed buckets + static const char* alpha(float a); // Return whether the original buffer is rotated in final composition static bool isRotated(int32_t transform); // Return whether the original buffer is V-flipped in final composition @@ -60,10 +67,10 @@ private: bool mEnabled = false; // Protect mLayersStatsMap std::mutex mMutex; - // Hashmap for tracking the layer stats - // KEY is a concatenation of a particular set of layer properties - // VALUE is the number of times this particular get scanned out - std::unordered_map mLayerStatsMap; + // Hashmap for tracking the frame(layer shape) stats + // KEY is a concatenation of all layers' properties within a frame + // VALUE is the number of times this particular set has been scanned out + std::unordered_map mLayerShapeStatsMap; }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b7931bc2af..e104727909 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1959,6 +1959,7 @@ void SurfaceFlinger::setUpHWComposer() { continue; } if (colorMatrix != mPreviousColorMatrix) { + displayDevice->setColorTransform(colorMatrix); status_t result = getBE().mHwc->setColorTransform(hwcId, colorMatrix); ALOGE_IF(result != NO_ERROR, "Failed to set color transform on " "display %zd: %d", displayId, result); @@ -4027,15 +4028,19 @@ LayersProto SurfaceFlinger::dumpProtoInfo(LayerVector::StateSet stateSet) const LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(int32_t hwcId) const { LayersProto layersProto; - const sp& displayDevice(mDisplays[hwcId]); + SizeProto* resolution = layersProto.mutable_resolution(); resolution->set_w(displayDevice->getWidth()); resolution->set_h(displayDevice->getHeight()); + layersProto.set_color_mode(decodeColorMode(displayDevice->getActiveColorMode())); + layersProto.set_color_transform(decodeColorTransform(displayDevice->getColorTransform())); + layersProto.set_global_transform( + static_cast(displayDevice->getOrientationTransform())); + mDrawingState.traverseInZOrder([&](Layer* layer) { - if (!layer->visibleRegion.isEmpty() && - layer->getBE().mHwcLayers.count(hwcId)) { + if (!layer->visibleRegion.isEmpty() && layer->getBE().mHwcLayers.count(hwcId)) { LayerProto* layerProto = layersProto.add_layers(); layer->writeToProto(layerProto, hwcId); } diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index b10e07b215..452592e8d6 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -44,7 +44,12 @@ bool sortLayerUniquePtrs(const std::unique_ptr& lhs, const LayerProtoParser::LayerGlobal LayerProtoParser::generateLayerGlobalInfo( const LayersProto& layersProto) { - return {{layersProto.resolution().w(), layersProto.resolution().h()}}; + LayerGlobal layerGlobal; + layerGlobal.resolution = {layersProto.resolution().w(), layersProto.resolution().h()}; + layerGlobal.colorMode = layersProto.color_mode(); + layerGlobal.colorTransform = layersProto.color_transform(); + layerGlobal.globalTransform = layersProto.global_transform(); + return layerGlobal; } std::vector> LayerProtoParser::generateLayerTree( @@ -116,6 +121,8 @@ LayerProtoParser::Layer* LayerProtoParser::generateLayer(const LayerProto& layer layer->hwcTransform = layerProto.hwc_transform(); layer->windowType = layerProto.window_type(); layer->appId = layerProto.app_id(); + layer->hwcCompositionType = layerProto.hwc_composition_type(); + layer->isProtected = layerProto.is_protected(); return layer; } diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index fd893da1b1..74a6f28f2b 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -112,6 +112,8 @@ public: int32_t hwcTransform; int32_t windowType; int32_t appId; + int32_t hwcCompositionType; + bool isProtected; std::string to_string() const; }; @@ -119,6 +121,9 @@ public: class LayerGlobal { public: int2 resolution; + std::string colorMode; + std::string colorTransform; + int32_t globalTransform; }; static const LayerGlobal generateLayerGlobalInfo(const LayersProto& layersProto); diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index 6675aae797..77c6675b7f 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -8,6 +8,9 @@ package android.surfaceflinger; message LayersProto { repeated LayerProto layers = 1; optional SizeProto resolution = 2; + optional string color_mode = 3; + optional string color_transform = 4; + optional int32 global_transform = 5; } // Information about each layer. @@ -73,6 +76,10 @@ message LayerProto { optional int32 hwc_transform = 32; optional int32 window_type = 33; optional int32 app_id = 34; + // The layer's composition type + optional int32 hwc_composition_type = 35; + // If it's a buffer layer, indicate if the content is protected + optional bool is_protected = 36; } message PositionProto { -- cgit v1.2.3-59-g8ed1b From faf3ded90b625a3a304c22d1574bea9d408dec57 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Wed, 2 May 2018 17:37:17 -0700 Subject: SurfaceFlinger TimeStats Metrics Add timestats metrics for SurfaceFlinger. Keep track of global metrics like total frames, missed frames, frames fellback to client compositions, etc, as well as layer timing metrics like the delta combination of postTime, desiredPresentTime, acqureTime, latchTime, presentTime, etc. This metric is aimed at GMScore. Test: dumpsys SurfaceFlinger --timestats [go/sf-timestats for more args] Bug: b/70388650 Change-Id: I6e4545aef62f7893020533a4e7521541ea453ecd --- services/surfaceflinger/Android.bp | 6 +- services/surfaceflinger/BufferLayer.cpp | 17 +- services/surfaceflinger/Layer.cpp | 6 + services/surfaceflinger/Layer.h | 5 +- services/surfaceflinger/SurfaceFlinger.cpp | 28 +- services/surfaceflinger/SurfaceFlinger.h | 2 + services/surfaceflinger/TimeStats/TimeStats.cpp | 498 +++++++++++++++++++++ services/surfaceflinger/TimeStats/TimeStats.h | 103 +++++ .../TimeStats/timestatsproto/Android.bp | 55 +++ .../TimeStats/timestatsproto/TimeStatsHelper.cpp | 156 +++++++ .../include/timestatsproto/TimeStatsHelper.h | 72 +++ .../include/timestatsproto/TimeStatsProtoHeader.h | 23 + .../TimeStats/timestatsproto/jarjar-rules.txt | 1 + .../TimeStats/timestatsproto/timestats.proto | 69 +++ services/surfaceflinger/tests/Android.bp | 1 + services/surfaceflinger/tests/fakehwc/Android.bp | 1 + 16 files changed, 1032 insertions(+), 11 deletions(-) create mode 100644 services/surfaceflinger/TimeStats/TimeStats.cpp create mode 100644 services/surfaceflinger/TimeStats/TimeStats.h create mode 100644 services/surfaceflinger/TimeStats/timestatsproto/Android.bp create mode 100644 services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp create mode 100644 services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h create mode 100644 services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsProtoHeader.h create mode 100644 services/surfaceflinger/TimeStats/timestatsproto/jarjar-rules.txt create mode 100644 services/surfaceflinger/TimeStats/timestatsproto/timestats.proto (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 6ffef3175e..cd366bdd8b 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -46,6 +46,7 @@ cc_defaults { "libpdx_default_transport", "libprotobuf-cpp-lite", "libsync", + "libtimestats_proto", "libui", "libutils", "libvulkan", @@ -106,7 +107,7 @@ filegroup { "FrameTracker.cpp", "GpuService.cpp", "Layer.cpp", - "LayerBE.cpp", + "LayerBE.cpp", "LayerProtoHelper.cpp", "LayerRejecter.cpp", "LayerStats.cpp", @@ -128,6 +129,7 @@ filegroup { "SurfaceFlinger.cpp", "SurfaceInterceptor.cpp", "SurfaceTracing.cpp", + "TimeStats/TimeStats.cpp", "Transform.cpp", ], } @@ -176,6 +178,7 @@ cc_binary { "liblayers_proto", "liblog", "libsurfaceflinger", + "libtimestats_proto", "libutils", ], static_libs: [ @@ -217,5 +220,6 @@ cc_library_shared { subdirs = [ "layerproto", + "TimeStats/timestatsproto", "tests", ] diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 250c2f1939..3c3eab602a 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -311,6 +311,9 @@ bool BufferLayer::onPostComposition(const std::shared_ptr& glDoneFenc nsecs_t desiredPresentTime = mConsumer->getTimestamp(); mFrameTracker.setDesiredPresentTime(desiredPresentTime); + const std::string layerName(getName().c_str()); + mTimeStats.setDesiredTime(layerName, mCurrentFrameNumber, desiredPresentTime); + std::shared_ptr frameReadyFence = mConsumer->getCurrentFenceTime(); if (frameReadyFence->isValid()) { mFrameTracker.setFrameReadyFence(std::move(frameReadyFence)); @@ -321,12 +324,15 @@ bool BufferLayer::onPostComposition(const std::shared_ptr& glDoneFenc } if (presentFence->isValid()) { + mTimeStats.setPresentFence(layerName, mCurrentFrameNumber, presentFence); mFrameTracker.setActualPresentFence(std::shared_ptr(presentFence)); } else { // The HWC doesn't support present fences, so use the refresh // timestamp instead. - mFrameTracker.setActualPresentTime( - mFlinger->getHwComposer().getRefreshTimestamp(HWC_DISPLAY_PRIMARY)); + const nsecs_t actualPresentTime = + mFlinger->getHwComposer().getRefreshTimestamp(HWC_DISPLAY_PRIMARY); + mTimeStats.setPresentTime(layerName, mCurrentFrameNumber, actualPresentTime); + mFrameTracker.setActualPresentTime(actualPresentTime); } mFrameTracker.advanceFrame(); @@ -433,6 +439,7 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime // and return early if (queuedBuffer) { Mutex::Autolock lock(mQueueItemLock); + mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber); mQueueItems.removeAt(0); android_atomic_dec(&mQueuedFrames); } @@ -446,6 +453,7 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime Mutex::Autolock lock(mQueueItemLock); mQueueItems.clear(); android_atomic_and(0, &mQueuedFrames); + mTimeStats.clearLayerRecord(getName().c_str()); } // Once we have hit this state, the shadow queue may no longer @@ -466,10 +474,15 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime // Remove any stale buffers that have been dropped during // updateTexImage while (mQueueItems[0].mFrameNumber != currentFrameNumber) { + mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber); mQueueItems.removeAt(0); android_atomic_dec(&mQueuedFrames); } + const std::string layerName(getName().c_str()); + mTimeStats.setAcquireFence(layerName, currentFrameNumber, mQueueItems[0].mFenceTime); + mTimeStats.setLatchTime(layerName, currentFrameNumber, latchTime); + mQueueItems.removeAt(0); } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index fc9f16b919..8a90083abb 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1528,10 +1528,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) { + 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 diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index d05a91bbc4..eda03ddb50 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -38,11 +38,12 @@ #include "Client.h" #include "FrameTracker.h" +#include "LayerBE.h" #include "LayerVector.h" #include "MonitoredProducer.h" #include "SurfaceFlinger.h" +#include "TimeStats/TimeStats.h" #include "Transform.h" -#include "LayerBE.h" #include #include "DisplayHardware/HWComposer.h" @@ -682,6 +683,8 @@ protected: FenceTimeline mAcquireTimeline; FenceTimeline mReleaseTimeline; + TimeStats& mTimeStats = TimeStats::getInstance(); + // main thread int mActiveBufferSlot; sp mActiveBuffer; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 46a1918a3f..abd74c1ca2 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1470,9 +1470,13 @@ void SurfaceFlinger::onMessageReceived(int32_t what) { Fence::SIGNAL_TIME_PENDING); ATRACE_INT("FrameMissed", static_cast(frameMissed)); if (mPropagateBackpressure && frameMissed) { + mTimeStats.incrementMissedFrames(true); signalLayerUpdate(); break; } + if (frameMissed) { + mTimeStats.incrementMissedFrames(false); + } // Now that we're going to make it to the handleMessageTransaction() // call below it's safe to call updateVrFlinger(), which will @@ -1771,6 +1775,11 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) mAnimFrameTracker.advanceFrame(); } + mTimeStats.incrementTotalFrames(); + if (mHadClientComposition) { + mTimeStats.incrementClientCompositionFrames(); + } + if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY) && hw->getPowerMode() == HWC_POWER_MODE_OFF) { return; @@ -3825,12 +3834,6 @@ status_t SurfaceFlinger::doDump(int fd, const Vector& args, bool asPro size_t index = 0; size_t numArgs = args.size(); - if (asProto) { - LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current); - result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize()); - dumpAll = false; - } - if (numArgs) { if ((index < numArgs) && (args[index] == String16("--list"))) { @@ -3914,10 +3917,21 @@ status_t SurfaceFlinger::doDump(int fd, const Vector& args, bool asPro dumpDisplayIdentificationData(result); dumpAll = false; } + + if ((index < numArgs) && (args[index] == String16("--timestats"))) { + index++; + mTimeStats.parseArgs(asProto, args, index, result); + dumpAll = false; + } } if (dumpAll) { - dumpAllLocked(args, index, result); + if (asProto) { + LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current); + result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize()); + } else { + dumpAllLocked(args, index, result); + } } if (locked) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 2086b4fcc2..3152a4e318 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -64,6 +64,7 @@ #include "SurfaceInterceptor.h" #include "SurfaceTracing.h" #include "StartPropertySetThread.h" +#include "TimeStats/TimeStats.h" #include "LayerBE.h" #include "VSyncModulator.h" @@ -818,6 +819,7 @@ private: std::make_unique(this); SurfaceTracing mTracing; LayerStats mLayerStats; + TimeStats& mTimeStats = TimeStats::getInstance(); bool mUseHwcVirtualDisplays = false; // Restrict layers to use two buffers in their bufferqueues. diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp new file mode 100644 index 0000000000..5f2dd32182 --- /dev/null +++ b/services/surfaceflinger/TimeStats/TimeStats.cpp @@ -0,0 +1,498 @@ +/* + * Copyright 2018 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. + */ +#undef LOG_TAG +#define LOG_TAG "TimeStats" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "TimeStats.h" + +#include + +#include + +#include +#include + +#include +#include + +namespace android { + +TimeStats& TimeStats::getInstance() { + static std::unique_ptr sInstance; + static std::once_flag sOnceFlag; + + std::call_once(sOnceFlag, [] { sInstance.reset(new TimeStats); }); + return *sInstance.get(); +} + +void TimeStats::parseArgs(bool asProto, const Vector& args, size_t& index, + String8& result) { + ATRACE_CALL(); + + if (args.size() > index + 10) { + ALOGD("Invalid args count"); + return; + } + + std::unordered_map argsMap; + while (index < args.size()) { + argsMap[std::string(String8(args[index]).c_str())] = index; + ++index; + } + + if (argsMap.count("-disable")) { + disable(); + } + + if (argsMap.count("-dump")) { + int64_t maxLayers = 0; + auto iter = argsMap.find("-maxlayers"); + if (iter != argsMap.end() && iter->second + 1 < static_cast(args.size())) { + maxLayers = strtol(String8(args[iter->second + 1]).c_str(), nullptr, 10); + maxLayers = std::clamp(maxLayers, int64_t(0), int64_t(UINT32_MAX)); + } + + dump(asProto, static_cast(maxLayers), result); + } + + if (argsMap.count("-clear")) { + clear(); + } + + if (argsMap.count("-enable")) { + enable(); + } +} + +void TimeStats::incrementTotalFrames() { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + + std::lock_guard lock(mMutex); + timeStats.totalFrames++; +} + +void TimeStats::incrementMissedFrames(bool propagateBackpressure) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + + std::lock_guard lock(mMutex); + if (propagateBackpressure) { + timeStats.totalFrames--; + } + timeStats.missedFrames++; +} + +void TimeStats::incrementClientCompositionFrames() { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + + std::lock_guard lock(mMutex); + timeStats.clientCompositionFrames++; +} + +bool TimeStats::recordReadyLocked(const std::string& layerName, TimeRecord* timeRecord) { + if (!timeRecord->ready) { + ALOGV("[%s]-[%" PRIu64 "]-presentFence is still not received", layerName.c_str(), + timeRecord->frameNumber); + return false; + } + + if (timeRecord->acquireFence != nullptr) { + if (timeRecord->acquireFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING) { + return false; + } + if (timeRecord->acquireFence->getSignalTime() != Fence::SIGNAL_TIME_INVALID) { + timeRecord->acquireTime = timeRecord->acquireFence->getSignalTime(); + timeRecord->acquireFence = nullptr; + } else { + ALOGV("[%s]-[%" PRIu64 "]-acquireFence signal time is invalid", layerName.c_str(), + timeRecord->frameNumber); + } + } + + if (timeRecord->presentFence != nullptr) { + if (timeRecord->presentFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING) { + return false; + } + if (timeRecord->presentFence->getSignalTime() != Fence::SIGNAL_TIME_INVALID) { + timeRecord->presentTime = timeRecord->presentFence->getSignalTime(); + timeRecord->presentFence = nullptr; + } else { + ALOGV("[%s]-[%" PRIu64 "]-presentFence signal time invalid", layerName.c_str(), + timeRecord->frameNumber); + } + } + + return true; +} + +static int32_t msBetween(nsecs_t start, nsecs_t end) { + int64_t delta = (end - start) / 1000000; + delta = std::clamp(delta, int64_t(INT32_MIN), int64_t(INT32_MAX)); + return static_cast(delta); +} + +void TimeStats::flushAvailableRecordsToStatsLocked(const std::string& layerName) { + ATRACE_CALL(); + + LayerRecord& layerRecord = timeStatsTracker[layerName]; + TimeRecord& prevTimeRecord = layerRecord.prevTimeRecord; + std::vector& timeRecords = layerRecord.timeRecords; + while (!timeRecords.empty()) { + if (!recordReadyLocked(layerName, &timeRecords[0])) break; + ALOGV("[%s]-[%" PRIu64 "]-presentFenceTime[%" PRId64 "]", layerName.c_str(), + timeRecords[0].frameNumber, timeRecords[0].presentTime); + + if (prevTimeRecord.ready) { + if (!timeStats.stats.count(layerName)) { + timeStats.stats[layerName].layerName = layerName; + timeStats.stats[layerName].statsStart = static_cast(std::time(0)); + } + TimeStatsHelper::TimeStatsLayer& timeStatsLayer = timeStats.stats[layerName]; + timeStatsLayer.totalFrames++; + + const int32_t postToPresentMs = + msBetween(timeRecords[0].postTime, timeRecords[0].presentTime); + ALOGV("[%s]-[%" PRIu64 "]-post2present[%d]", layerName.c_str(), + timeRecords[0].frameNumber, postToPresentMs); + timeStatsLayer.deltas["post2present"].insert(postToPresentMs); + + const int32_t acquireToPresentMs = + msBetween(timeRecords[0].acquireTime, timeRecords[0].presentTime); + ALOGV("[%s]-[%" PRIu64 "]-acquire2present[%d]", layerName.c_str(), + timeRecords[0].frameNumber, acquireToPresentMs); + timeStatsLayer.deltas["acquire2present"].insert(acquireToPresentMs); + + const int32_t latchToPresentMs = + msBetween(timeRecords[0].latchTime, timeRecords[0].presentTime); + ALOGV("[%s]-[%" PRIu64 "]-latch2present[%d]", layerName.c_str(), + timeRecords[0].frameNumber, latchToPresentMs); + timeStatsLayer.deltas["latch2present"].insert(latchToPresentMs); + + const int32_t desiredToPresentMs = + msBetween(timeRecords[0].desiredTime, timeRecords[0].presentTime); + ALOGV("[%s]-[%" PRIu64 "]-desired2present[%d]", layerName.c_str(), + timeRecords[0].frameNumber, desiredToPresentMs); + timeStatsLayer.deltas["desired2present"].insert(desiredToPresentMs); + + const int32_t presentToPresentMs = + msBetween(prevTimeRecord.presentTime, timeRecords[0].presentTime); + ALOGV("[%s]-[%" PRIu64 "]-present2present[%d]", layerName.c_str(), + timeRecords[0].frameNumber, presentToPresentMs); + timeStatsLayer.deltas["present2present"].insert(presentToPresentMs); + + timeStats.stats[layerName].statsEnd = static_cast(std::time(0)); + } + prevTimeRecord = timeRecords[0]; + // TODO(zzyiwei): change timeRecords to use std::deque + timeRecords.erase(timeRecords.begin()); + layerRecord.waitData--; + } +} + +static bool layerNameIsValid(const std::string& layerName) { + // This regular expression captures the following layer names for instance: + // 1) StatusBat#0 + // 2) NavigationBar#1 + // 3) com.*#0 + // 4) SurfaceView - com.*#0 + // Using [-\\s\t]+ for the conjunction part between SurfaceView and com.* is + // a bit more robust in case there's a slight change. + // The layer name would only consist of . / $ _ 0-9 a-z A-Z in most cases. + std::regex re("(((SurfaceView[-\\s\\t]+)?com\\.[./$\\w]+)|((Status|Navigation)Bar))#\\d+"); + return std::regex_match(layerName.begin(), layerName.end(), re); +} + +void TimeStats::setPostTime(const std::string& layerName, uint64_t frameNumber, nsecs_t postTime) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%s]-[%" PRIu64 "]-PostTime[%" PRId64 "]", layerName.c_str(), frameNumber, postTime); + + std::lock_guard lock(mMutex); + if (!timeStatsTracker.count(layerName) && !layerNameIsValid(layerName)) { + return; + } + LayerRecord& layerRecord = timeStatsTracker[layerName]; + if (layerRecord.timeRecords.size() == MAX_NUM_TIME_RECORDS) { + ALOGV("[%s]-timeRecords is already at its maximum size[%zu]", layerName.c_str(), + MAX_NUM_TIME_RECORDS); + // TODO(zzyiwei): if this happens, there must be a present fence missing + // or waitData is not in the correct position. Need to think out a + // reasonable way to recover from this state. + return; + } + // For most media content, the acquireFence is invalid because the buffer is + // ready at the queueBuffer stage. In this case, acquireTime should be given + // a default value as postTime. + TimeRecord timeRecord = { + .frameNumber = frameNumber, + .postTime = postTime, + .acquireTime = postTime, + }; + layerRecord.timeRecords.push_back(timeRecord); + if (layerRecord.waitData < 0 || + layerRecord.waitData >= static_cast(layerRecord.timeRecords.size())) + layerRecord.waitData = layerRecord.timeRecords.size() - 1; +} + +void TimeStats::setLatchTime(const std::string& layerName, uint64_t frameNumber, + nsecs_t latchTime) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%s]-[%" PRIu64 "]-LatchTime[%" PRId64 "]", layerName.c_str(), frameNumber, latchTime); + + std::lock_guard lock(mMutex); + if (!timeStatsTracker.count(layerName)) return; + LayerRecord& layerRecord = timeStatsTracker[layerName]; + TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; + if (timeRecord.frameNumber == frameNumber) { + timeRecord.latchTime = latchTime; + } +} + +void TimeStats::setDesiredTime(const std::string& layerName, uint64_t frameNumber, + nsecs_t desiredTime) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%s]-[%" PRIu64 "]-DesiredTime[%" PRId64 "]", layerName.c_str(), frameNumber, + desiredTime); + + std::lock_guard lock(mMutex); + if (!timeStatsTracker.count(layerName)) return; + LayerRecord& layerRecord = timeStatsTracker[layerName]; + TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; + if (timeRecord.frameNumber == frameNumber) { + timeRecord.desiredTime = desiredTime; + } +} + +void TimeStats::setAcquireTime(const std::string& layerName, uint64_t frameNumber, + nsecs_t acquireTime) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%s]-[%" PRIu64 "]-AcquireTime[%" PRId64 "]", layerName.c_str(), frameNumber, + acquireTime); + + std::lock_guard lock(mMutex); + if (!timeStatsTracker.count(layerName)) return; + LayerRecord& layerRecord = timeStatsTracker[layerName]; + TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; + if (timeRecord.frameNumber == frameNumber) { + timeRecord.acquireTime = acquireTime; + } +} + +void TimeStats::setAcquireFence(const std::string& layerName, uint64_t frameNumber, + const std::shared_ptr& acquireFence) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%s]-[%" PRIu64 "]-AcquireFenceTime[%" PRId64 "]", layerName.c_str(), frameNumber, + acquireFence->getSignalTime()); + + std::lock_guard lock(mMutex); + if (!timeStatsTracker.count(layerName)) return; + LayerRecord& layerRecord = timeStatsTracker[layerName]; + TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; + if (timeRecord.frameNumber == frameNumber) { + timeRecord.acquireFence = acquireFence; + } +} + +void TimeStats::setPresentTime(const std::string& layerName, uint64_t frameNumber, + nsecs_t presentTime) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%s]-[%" PRIu64 "]-PresentTime[%" PRId64 "]", layerName.c_str(), frameNumber, + presentTime); + + std::lock_guard lock(mMutex); + if (!timeStatsTracker.count(layerName)) return; + LayerRecord& layerRecord = timeStatsTracker[layerName]; + TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; + if (timeRecord.frameNumber == frameNumber) { + timeRecord.presentTime = presentTime; + timeRecord.ready = true; + layerRecord.waitData++; + } + + flushAvailableRecordsToStatsLocked(layerName); +} + +void TimeStats::setPresentFence(const std::string& layerName, uint64_t frameNumber, + const std::shared_ptr& presentFence) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%s]-[%" PRIu64 "]-PresentFenceTime[%" PRId64 "]", layerName.c_str(), frameNumber, + presentFence->getSignalTime()); + + std::lock_guard lock(mMutex); + if (!timeStatsTracker.count(layerName)) return; + LayerRecord& layerRecord = timeStatsTracker[layerName]; + TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; + if (timeRecord.frameNumber == frameNumber) { + timeRecord.presentFence = presentFence; + timeRecord.ready = true; + layerRecord.waitData++; + } + + flushAvailableRecordsToStatsLocked(layerName); +} + +void TimeStats::onDisconnect(const std::string& layerName) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%s]-onDisconnect", layerName.c_str()); + + std::lock_guard lock(mMutex); + if (!timeStatsTracker.count(layerName)) return; + flushAvailableRecordsToStatsLocked(layerName); + timeStatsTracker.erase(layerName); +} + +void TimeStats::clearLayerRecord(const std::string& layerName) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%s]-clearLayerRecord", layerName.c_str()); + + std::lock_guard lock(mMutex); + if (!timeStatsTracker.count(layerName)) return; + LayerRecord& layerRecord = timeStatsTracker[layerName]; + layerRecord.timeRecords.clear(); + layerRecord.prevTimeRecord.ready = false; + layerRecord.waitData = -1; +} + +void TimeStats::removeTimeRecord(const std::string& layerName, uint64_t frameNumber) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%s]-[%" PRIu64 "]-removeTimeRecord", layerName.c_str(), frameNumber); + + std::lock_guard lock(mMutex); + if (!timeStatsTracker.count(layerName)) return; + LayerRecord& layerRecord = timeStatsTracker[layerName]; + size_t removeAt = 0; + for (const TimeRecord& record : layerRecord.timeRecords) { + if (record.frameNumber == frameNumber) break; + removeAt++; + } + if (removeAt == layerRecord.timeRecords.size()) return; + layerRecord.timeRecords.erase(layerRecord.timeRecords.begin() + removeAt); + if (layerRecord.waitData > static_cast(removeAt)) { + --layerRecord.waitData; + } +} + +void TimeStats::enable() { + if (mEnabled.load()) return; + + ATRACE_CALL(); + + std::lock_guard lock(mMutex); + ALOGD("Enabled"); + mEnabled.store(true); + timeStats.statsStart = static_cast(std::time(0)); +} + +void TimeStats::disable() { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + + std::lock_guard lock(mMutex); + ALOGD("Disabled"); + mEnabled.store(false); + timeStats.statsEnd = static_cast(std::time(0)); +} + +void TimeStats::clear() { + ATRACE_CALL(); + + std::lock_guard lock(mMutex); + ALOGD("Cleared"); + timeStats.dumpStats.clear(); + timeStats.stats.clear(); + timeStats.statsStart = (mEnabled.load() ? static_cast(std::time(0)) : 0); + timeStats.statsEnd = 0; + timeStats.totalFrames = 0; + timeStats.missedFrames = 0; + timeStats.clientCompositionFrames = 0; +} + +bool TimeStats::isEnabled() { + return mEnabled.load(); +} + +void TimeStats::dump(bool asProto, uint32_t maxLayers, String8& result) { + ATRACE_CALL(); + + std::lock_guard lock(mMutex); + if (timeStats.statsStart == 0) { + return; + } + + timeStats.statsEnd = static_cast(std::time(0)); + + // TODO(zzyiwei): refactor dumpStats into TimeStatsHelper + timeStats.dumpStats.clear(); + for (auto& ele : timeStats.stats) { + timeStats.dumpStats.push_back(&ele.second); + } + + std::sort(timeStats.dumpStats.begin(), timeStats.dumpStats.end(), + [](TimeStatsHelper::TimeStatsLayer* const& l, + TimeStatsHelper::TimeStatsLayer* const& r) { + return l->totalFrames > r->totalFrames; + }); + + if (maxLayers != 0 && maxLayers < timeStats.dumpStats.size()) { + timeStats.dumpStats.resize(maxLayers); + } + + if (asProto) { + dumpAsProtoLocked(result); + } else { + dumpAsTextLocked(result); + } +} + +void TimeStats::dumpAsTextLocked(String8& result) { + ALOGD("Dumping TimeStats as text"); + result.append(timeStats.toString().c_str()); + result.append("\n"); +} + +void TimeStats::dumpAsProtoLocked(String8& result) { + ALOGD("Dumping TimeStats as proto"); + SFTimeStatsGlobalProto timeStatsProto = timeStats.toProto(); + result.append(timeStatsProto.SerializeAsString().c_str(), timeStatsProto.ByteSize()); +} + +} // namespace android diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h new file mode 100644 index 0000000000..2410265a0d --- /dev/null +++ b/services/surfaceflinger/TimeStats/TimeStats.h @@ -0,0 +1,103 @@ +/* + * Copyright 2018 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 +#include + +#include + +#include +#include +#include + +#include +#include +#include + +using namespace android::surfaceflinger; + +namespace android { +class String8; + +class TimeStats { + // TODO(zzyiwei): Bound the timeStatsTracker with weighted LRU + // static const size_t MAX_NUM_LAYER_RECORDS = 200; + static const size_t MAX_NUM_TIME_RECORDS = 64; + + struct TimeRecord { + bool ready = false; + uint64_t frameNumber = 0; + nsecs_t postTime = 0; + nsecs_t latchTime = 0; + nsecs_t acquireTime = 0; + nsecs_t desiredTime = 0; + nsecs_t presentTime = 0; + std::shared_ptr acquireFence; + std::shared_ptr presentFence; + }; + + struct LayerRecord { + // This is the index in timeRecords, at which the timestamps for that + // specific frame are still not fully received. This is not waiting for + // fences to signal, but rather waiting to receive those fences/timestamps. + int32_t waitData = -1; + TimeRecord prevTimeRecord; + std::vector timeRecords; + }; + +public: + static TimeStats& getInstance(); + void parseArgs(bool asProto, const Vector& args, size_t& index, String8& result); + void incrementTotalFrames(); + void incrementMissedFrames(bool propagateBackpressure); + void incrementClientCompositionFrames(); + + void setPostTime(const std::string& layerName, uint64_t frameNumber, nsecs_t postTime); + void setLatchTime(const std::string& layerName, uint64_t frameNumber, nsecs_t latchTime); + void setDesiredTime(const std::string& layerName, uint64_t frameNumber, nsecs_t desiredTime); + void setAcquireTime(const std::string& layerName, uint64_t frameNumber, nsecs_t acquireTime); + void setAcquireFence(const std::string& layerName, uint64_t frameNumber, + const std::shared_ptr& acquireFence); + void setPresentTime(const std::string& layerName, uint64_t frameNumber, nsecs_t presentTime); + void setPresentFence(const std::string& layerName, uint64_t frameNumber, + const std::shared_ptr& presentFence); + void onDisconnect(const std::string& layerName); + void clearLayerRecord(const std::string& layerName); + void removeTimeRecord(const std::string& layerName, uint64_t frameNumber); + +private: + TimeStats() = default; + + bool recordReadyLocked(const std::string& layerName, TimeRecord* timeRecord); + void flushAvailableRecordsToStatsLocked(const std::string& layerName); + + void enable(); + void disable(); + void clear(); + bool isEnabled(); + void dump(bool asProto, uint32_t maxLayer, String8& result); + void dumpAsTextLocked(String8& result); + void dumpAsProtoLocked(String8& result); + + std::atomic mEnabled = false; + std::mutex mMutex; + TimeStatsHelper::TimeStatsGlobal timeStats; + std::unordered_map timeStatsTracker; +}; + +} // namespace android diff --git a/services/surfaceflinger/TimeStats/timestatsproto/Android.bp b/services/surfaceflinger/TimeStats/timestatsproto/Android.bp new file mode 100644 index 0000000000..66aa719381 --- /dev/null +++ b/services/surfaceflinger/TimeStats/timestatsproto/Android.bp @@ -0,0 +1,55 @@ +cc_library_shared { + name: "libtimestats_proto", + vendor_available: true, + export_include_dirs: ["include"], + + srcs: [ + "TimeStatsHelper.cpp", + "timestats.proto", + ], + + shared_libs: [ + "android.hardware.graphics.common@1.1", + "libui", + "libprotobuf-cpp-lite", + "libbase", + "liblog", + ], + + proto: { + export_proto_headers: true, + }, + + cppflags: [ + "-Werror", + "-Wno-unused-parameter", + "-Wno-format", + "-Wno-c++98-compat-pedantic", + "-Wno-float-conversion", + "-Wno-disabled-macro-expansion", + "-Wno-float-equal", + "-Wno-sign-conversion", + "-Wno-padded", + "-Wno-old-style-cast", + "-Wno-undef", + ], + +} + +java_library_static { + name: "timestatsprotosnano", + host_supported: true, + proto: { + type: "nano", + }, + srcs: ["*.proto"], + no_framework_libs: true, + target: { + android: { + jarjar_rules: "jarjar-rules.txt", + }, + host: { + static_libs: ["libprotobuf-java-nano"], + }, + }, +} diff --git a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp new file mode 100644 index 0000000000..ec0570d619 --- /dev/null +++ b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp @@ -0,0 +1,156 @@ +/* + * 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. + */ +#include +#include + +#include +#include + +#define HISTOGRAM_SIZE 85 + +using android::base::StringAppendF; +using android::base::StringPrintf; + +namespace android { +namespace surfaceflinger { + +// Time buckets for histogram, the calculated time deltas will be lower bounded +// to the buckets in this array. +static const std::array histogramConfig = + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 36, 38, 40, 42, 44, 46, 48, 50, 54, 58, 62, 66, 70, 74, 78, 82, + 86, 90, 94, 98, 102, 106, 110, 114, 118, 122, 126, 130, 134, 138, 142, 146, 150, + 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800, 850, 900, 950, 1000}; + +void TimeStatsHelper::Histogram::insert(int32_t delta) { + if (delta < 0) return; + // std::lower_bound won't work on out of range values + if (delta > histogramConfig[HISTOGRAM_SIZE - 1]) { + hist[histogramConfig[HISTOGRAM_SIZE - 1]]++; + return; + } + auto iter = std::lower_bound(histogramConfig.begin(), histogramConfig.end(), delta); + hist[*iter]++; +} + +float TimeStatsHelper::Histogram::averageTime() { + int64_t ret = 0; + int64_t count = 0; + for (auto ele : hist) { + count += ele.second; + ret += ele.first * ele.second; + } + return static_cast(ret) / count; +} + +std::string TimeStatsHelper::Histogram::toString() { + std::string result; + for (int32_t i = 0; i < HISTOGRAM_SIZE; ++i) { + int32_t bucket = histogramConfig[i]; + int32_t count = (hist.count(bucket) == 0) ? 0 : hist[bucket]; + StringAppendF(&result, "%dms=%d ", bucket, count); + } + result.back() = '\n'; + return result; +} + +static std::string getPackageName(const std::string& layerName) { + // This regular expression captures the following for instance: + // StatusBar in StatusBar#0 + // com.appname in com.appname/com.appname.activity#0 + // com.appname in SurfaceView - com.appname/com.appname.activity#0 + const std::regex re("(?:SurfaceView[-\\s\\t]+)?([^/]+).*#\\d+"); + std::smatch match; + if (std::regex_match(layerName.begin(), layerName.end(), match, re)) { + // There must be a match for group 1 otherwise the whole string is not + // matched and the above will return false + return match[1]; + } + return ""; +} + +std::string TimeStatsHelper::TimeStatsLayer::toString() { + std::string result = ""; + StringAppendF(&result, "layerName = %s\n", layerName.c_str()); + packageName = getPackageName(layerName); + StringAppendF(&result, "packageName = %s\n", packageName.c_str()); + StringAppendF(&result, "statsStart = %lld\n", static_cast(statsStart)); + StringAppendF(&result, "statsEnd = %lld\n", static_cast(statsEnd)); + StringAppendF(&result, "totalFrames= %d\n", totalFrames); + if (deltas.find("present2present") != deltas.end()) { + StringAppendF(&result, "averageFPS = %.3f\n", + 1000.0 / deltas["present2present"].averageTime()); + } + for (auto ele : deltas) { + StringAppendF(&result, "%s histogram is as below:\n", ele.first.c_str()); + StringAppendF(&result, "%s", ele.second.toString().c_str()); + } + + return result; +} + +std::string TimeStatsHelper::TimeStatsGlobal::toString() { + std::string result = "SurfaceFlinger TimeStats:\n"; + StringAppendF(&result, "statsStart = %lld\n", static_cast(statsStart)); + StringAppendF(&result, "statsEnd = %lld\n", static_cast(statsEnd)); + StringAppendF(&result, "totalFrames= %d\n", totalFrames); + StringAppendF(&result, "missedFrames= %d\n", missedFrames); + StringAppendF(&result, "clientCompositionFrames= %d\n", clientCompositionFrames); + StringAppendF(&result, "TimeStats for each layer is as below:\n"); + for (auto ele : dumpStats) { + StringAppendF(&result, "%s", ele->toString().c_str()); + } + + return result; +} + +SFTimeStatsLayerProto TimeStatsHelper::TimeStatsLayer::toProto() { + SFTimeStatsLayerProto layerProto; + layerProto.set_layer_name(layerName); + packageName = getPackageName(layerName); + layerProto.set_package_name(packageName); + layerProto.set_stats_start(statsStart); + layerProto.set_stats_end(statsEnd); + layerProto.set_total_frames(totalFrames); + for (auto ele : deltas) { + SFTimeStatsDeltaProto* deltaProto = layerProto.add_deltas(); + deltaProto->set_delta_name(ele.first); + SFTimeStatsHistogramBucketProto* histProto = deltaProto->add_histograms(); + for (auto histEle : ele.second.hist) { + histProto->set_render_millis(histEle.first); + histProto->set_frame_count(histEle.second); + } + } + return layerProto; +} + +SFTimeStatsGlobalProto TimeStatsHelper::TimeStatsGlobal::toProto() { + SFTimeStatsGlobalProto globalProto; + globalProto.set_stats_start(statsStart); + globalProto.set_stats_end(statsEnd); + globalProto.set_total_frames(totalFrames); + globalProto.set_missed_frames(missedFrames); + globalProto.set_client_composition_frames(clientCompositionFrames); + for (auto ele : dumpStats) { + SFTimeStatsLayerProto* layerProto = globalProto.add_stats(); + layerProto->CopyFrom(ele->toProto()); + } + return globalProto; +} + +} // namespace surfaceflinger +} // namespace android diff --git a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h new file mode 100644 index 0000000000..c876f21404 --- /dev/null +++ b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2018 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 + +#include + +#include +#include +#include +#include + +namespace android { +namespace surfaceflinger { + +class TimeStatsHelper { +public: + class Histogram { + public: + // Key is the delta time between timestamps + // Value is the number of appearances of that delta + std::unordered_map hist; + + void insert(int32_t delta); + float averageTime(); + std::string toString(); + }; + + class TimeStatsLayer { + public: + std::string layerName; + std::string packageName; + int64_t statsStart = 0; + int64_t statsEnd = 0; + int32_t totalFrames = 0; + std::unordered_map deltas; + + std::string toString(); + SFTimeStatsLayerProto toProto(); + }; + + class TimeStatsGlobal { + public: + int64_t statsStart = 0; + int64_t statsEnd = 0; + int32_t totalFrames = 0; + int32_t missedFrames = 0; + int32_t clientCompositionFrames = 0; + std::unordered_map stats; + std::vector dumpStats; + + std::string toString(); + SFTimeStatsGlobalProto toProto(); + }; +}; + +} // namespace surfaceflinger +} // namespace android diff --git a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsProtoHeader.h b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsProtoHeader.h new file mode 100644 index 0000000000..fe0d150c3b --- /dev/null +++ b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsProtoHeader.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 The Android Open Source Projectlayerproto/LayerProtoHeader.h + * + * 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 is used here to disable the warnings emitted from the protobuf +// headers. By adding #pragma before including layer.pb.h, it supresses +// protobuf warnings, but allows the rest of the files to continuing using +// the current flags. +// This file should be included instead of directly including layer.b.h +#pragma GCC system_header +#include diff --git a/services/surfaceflinger/TimeStats/timestatsproto/jarjar-rules.txt b/services/surfaceflinger/TimeStats/timestatsproto/jarjar-rules.txt new file mode 100644 index 0000000000..40043a861c --- /dev/null +++ b/services/surfaceflinger/TimeStats/timestatsproto/jarjar-rules.txt @@ -0,0 +1 @@ +rule com.google.protobuf.nano.** com.android.framework.protobuf.nano.@1 diff --git a/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto b/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto new file mode 100644 index 0000000000..a8f6fa8ab1 --- /dev/null +++ b/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto @@ -0,0 +1,69 @@ +/* + * Copyright 2018 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. + */ + +syntax = "proto2"; + +package android.surfaceflinger; + +option optimize_for = LITE_RUNTIME; + +// frameworks/base/core/proto/android/service/sftimestats.proto is based on +// this proto. Please only make valid protobuf changes to these messages, and +// keep the other file in sync with this one. + +message SFTimeStatsGlobalProto { + // The start & end timestamps in UTC as + // milliseconds since January 1, 1970 + optional int64 stats_start = 1; + optional int64 stats_end = 2; + // Total frames + optional int32 total_frames = 3; + // Total missed frames of SurfaceFlinger. + optional int32 missed_frames = 4; + // Total frames fallback to client composition. + optional int32 client_composition_frames = 5; + + repeated SFTimeStatsLayerProto stats = 6; +} + +message SFTimeStatsLayerProto { + // The layer name + optional string layer_name = 1; + // The package name + optional string package_name = 2; + // The start & end timestamps in UTC as + // milliseconds since January 1, 1970 + optional int64 stats_start = 3; + optional int64 stats_end = 4; + // Distinct frame count. + optional int32 total_frames = 5; + + repeated SFTimeStatsDeltaProto deltas = 6; +} + +message SFTimeStatsDeltaProto { + // Name of the time interval + optional string delta_name = 1; + // Histogram of the delta time + repeated SFTimeStatsHistogramBucketProto histograms = 2; +} + +message SFTimeStatsHistogramBucketProto { + // Lower bound of render time in milliseconds. + optional int32 render_millis = 1; + // Number of frames in the bucket. + optional int32 frame_count = 2; +} diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp index 7523399dbf..322e8a0fea 100644 --- a/services/surfaceflinger/tests/Android.bp +++ b/services/surfaceflinger/tests/Android.bp @@ -36,6 +36,7 @@ cc_test { "liblayers_proto", "liblog", "libprotobuf-cpp-full", + "libtimestats_proto", "libui", "libutils", ] diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp index 00bc621df0..520df2d63f 100644 --- a/services/surfaceflinger/tests/fakehwc/Android.bp +++ b/services/surfaceflinger/tests/fakehwc/Android.bp @@ -25,6 +25,7 @@ cc_test { "liblog", "libnativewindow", "libsync", + "libtimestats_proto", "libui", "libutils", ], -- cgit v1.2.3-59-g8ed1b From 01591c94eaf64e42dd74b6c4d47c4c5d8b654557 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Tue, 22 May 2018 12:03:00 -0700 Subject: surfaceflinger: layer dataspace is not a state Like current crop or transform, layer dataspace is latched with the buffer. It is not a layer state, and should take effect immediately. Bug: 80139629 Test: manual Change-Id: I52342ca345f174e647550b45defa977484db95a1 --- services/surfaceflinger/BufferLayer.cpp | 12 ++++++------ services/surfaceflinger/ColorLayer.cpp | 4 ++-- services/surfaceflinger/Layer.cpp | 20 +++++++------------- services/surfaceflinger/Layer.h | 5 +++-- services/surfaceflinger/SurfaceFlinger.cpp | 10 +++++----- 5 files changed, 23 insertions(+), 28 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index f585bcc40f..6cdb1fd9ab 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -546,7 +546,7 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime default: break; } - setDataSpace(dataSpace); + mCurrentDataSpace = dataSpace; Rect crop(mConsumer->getCurrentCrop()); const uint32_t transform(mConsumer->getCurrentTransform()); @@ -651,10 +651,10 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) setCompositionType(hwcId, HWC2::Composition::Device); } - ALOGV("setPerFrameData: dataspace = %d", mDrawingState.dataSpace); - error = (*hwcLayer)->setDataspace(mDrawingState.dataSpace); + ALOGV("setPerFrameData: dataspace = %d", mCurrentDataSpace); + error = (*hwcLayer)->setDataspace(mCurrentDataSpace); if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mDrawingState.dataSpace, + ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace, to_string(error).c_str(), static_cast(error)); } @@ -854,9 +854,9 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT auto& engine(mFlinger->getRenderEngine()); engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), false /* disableTexture */, getColor()); - engine.setSourceDataSpace(mCurrentState.dataSpace); + engine.setSourceDataSpace(mCurrentDataSpace); - if (mCurrentState.dataSpace == ui::Dataspace::BT2020_ITU_PQ && + if (mCurrentDataSpace == ui::Dataspace::BT2020_ITU_PQ && mConsumer->getCurrentApi() == NATIVE_WINDOW_API_MEDIA && getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102) { engine.setSourceY410BT2020(true); diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 09103a9c37..e79935383e 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -77,9 +77,9 @@ void ColorLayer::setPerFrameData(const sp& displayDevice) { setCompositionType(hwcId, HWC2::Composition::SolidColor); - error = (*hwcLayer)->setDataspace(mDrawingState.dataSpace); + error = (*hwcLayer)->setDataspace(mCurrentDataSpace); if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mDrawingState.dataSpace, + ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace, to_string(error).c_str(), static_cast(error)); } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 9d9b364291..13849933e8 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -119,7 +119,6 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n mCurrentState.layerStack = 0; mCurrentState.sequence = 0; mCurrentState.requested = mCurrentState.active; - mCurrentState.dataSpace = ui::Dataspace::UNKNOWN; mCurrentState.appId = 0; mCurrentState.type = 0; @@ -1324,15 +1323,6 @@ bool Layer::setLayerStack(uint32_t layerStack) { return true; } -bool Layer::setDataSpace(ui::Dataspace dataSpace) { - if (mCurrentState.dataSpace == dataSpace) return false; - mCurrentState.sequence++; - mCurrentState.dataSpace = dataSpace; - mCurrentState.modified = true; - setTransactionFlags(eTransactionNeeded); - return true; -} - uint32_t Layer::getLayerStack() const { auto p = mDrawingParent.promote(); if (p == nullptr) { @@ -1425,7 +1415,7 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mColor = ds.color; info.mFlags = ds.flags; info.mPixelFormat = getPixelFormat(); - info.mDataSpace = static_cast(ds.dataSpace); + info.mDataSpace = static_cast(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]; @@ -1644,7 +1634,7 @@ bool Layer::detachChildren() { bool Layer::isLegacyDataSpace() const { // return true when no higher bits are set - return !(mDrawingState.dataSpace & (ui::Dataspace::STANDARD_MASK | + return !(mCurrentDataSpace & (ui::Dataspace::STANDARD_MASK | ui::Dataspace::TRANSFER_MASK | ui::Dataspace::RANGE_MASK)); } @@ -1952,7 +1942,10 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) layerInfo->set_is_opaque(isOpaque(state)); layerInfo->set_invalidate(contentDirty); - layerInfo->set_dataspace(dataspaceDetails(static_cast(state.dataSpace))); + + // XXX (b/79210409) mCurrentDataSpace is not protected + layerInfo->set_dataspace(dataspaceDetails(static_cast(mCurrentDataSpace))); + layerInfo->set_pixel_format(decodePixelFormat(getPixelFormat())); LayerProtoHelper::writeToProto(getColor(), layerInfo->mutable_color()); LayerProtoHelper::writeToProto(state.color, layerInfo->mutable_requested_color()); @@ -1971,6 +1964,7 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) 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()); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 0e1bf85698..182ef8ad29 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -146,7 +146,6 @@ public: // dependent. Region activeTransparentRegion; Region requestedTransparentRegion; - ui::Dataspace dataSpace; int32_t appId; int32_t type; @@ -224,7 +223,6 @@ public: bool setTransparentRegionHint(const Region& transparent); bool setFlags(uint8_t flags, uint8_t mask); bool setLayerStack(uint32_t layerStack); - bool setDataSpace(ui::Dataspace dataSpace); uint32_t getLayerStack() const; void deferTransactionUntil(const sp& barrierHandle, uint64_t frameNumber); void deferTransactionUntil(const sp& barrierLayer, uint64_t frameNumber); @@ -235,6 +233,8 @@ public: bool reparent(const sp& newParentHandle); bool detachChildren(); + ui::Dataspace getDataSpace() const { return mCurrentDataSpace; } + // Before color management is introduced, contents on Android have to be // desaturated in order to match what they appears like visually. // With color management, these contents will appear desaturated, thus @@ -688,6 +688,7 @@ protected: int mActiveBufferSlot; sp mActiveBuffer; sp mSidebandStream; + ui::Dataspace mCurrentDataSpace = ui::Dataspace::UNKNOWN; Rect mCurrentCrop; uint32_t mCurrentTransform; // We encode unset as -1. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 54de3e56ab..5d6f440e12 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1880,7 +1880,7 @@ Dataspace SurfaceFlinger::getBestDataspace( *outHdrDataSpace = Dataspace::UNKNOWN; for (const auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - switch (layer->getDrawingState().dataSpace) { + switch (layer->getDataSpace()) { case Dataspace::V0_SCRGB: case Dataspace::V0_SCRGB_LINEAR: bestDataSpace = Dataspace::V0_SCRGB_LINEAR; @@ -2098,13 +2098,13 @@ void SurfaceFlinger::setUpHWComposer() { "display %zd: %d", displayId, result); } for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - if ((layer->getDrawingState().dataSpace == Dataspace::BT2020_PQ || - layer->getDrawingState().dataSpace == Dataspace::BT2020_ITU_PQ) && + if ((layer->getDataSpace() == Dataspace::BT2020_PQ || + layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) && !displayDevice->hasHDR10Support()) { layer->forceClientComposition(hwcId); } - if ((layer->getDrawingState().dataSpace == Dataspace::BT2020_HLG || - layer->getDrawingState().dataSpace == Dataspace::BT2020_ITU_HLG) && + if ((layer->getDataSpace() == Dataspace::BT2020_HLG || + layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) && !displayDevice->hasHLGSupport()) { layer->forceClientComposition(hwcId); } -- cgit v1.2.3-59-g8ed1b From f6a38939ecf3788a512d9ec5ec15533a5a57346c Mon Sep 17 00:00:00 2001 From: David Sodman Date: Fri, 25 May 2018 15:27:50 -0700 Subject: Revert "SF: use shared_ptr to track hwcLayer" This reverts commit 5d89c1d614426144b6430868a69db2b29b179213. The original commit was part of a larger set that has been backed out temporarily while some bugs are sorted out. This change should have been backed out as well as it depends on the others in the larger change. Test: run cts -m CtsViewTestCases Bug: 79264214 Change-Id: Ifa9388d9f9573073832a40075317fdabf74b180c --- services/surfaceflinger/BufferLayer.cpp | 12 +++++------ services/surfaceflinger/ColorLayer.cpp | 8 ++++---- services/surfaceflinger/Layer.cpp | 36 ++++++++++++++++----------------- services/surfaceflinger/Layer.h | 10 +-------- services/surfaceflinger/LayerBE.cpp | 2 +- services/surfaceflinger/LayerBE.h | 29 ++------------------------ 6 files changed, 32 insertions(+), 65 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 6cdb1fd9ab..f714effdbd 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -615,14 +615,14 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) auto hwcId = displayDevice->getHwcDisplayId(); auto& hwcInfo = getBE().mHwcLayers[hwcId]; auto& hwcLayer = hwcInfo.layer; - auto error = (*hwcLayer)->setVisibleRegion(visible); + 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(error)); visible.dump(LOG_TAG); } - error = (*hwcLayer)->setSurfaceDamage(surfaceDamageRegion); + 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(error)); @@ -633,7 +633,7 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) if (getBE().compositionInfo.hwc.sidebandStream.get()) { setCompositionType(hwcId, HWC2::Composition::Sideband); ALOGV("[%s] Requesting Sideband composition", mName.string()); - error = (*hwcLayer)->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle()); + error = hwcLayer->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle()); if (error != HWC2::Error::None) { ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(), getBE().compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(), @@ -652,14 +652,14 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) } ALOGV("setPerFrameData: dataspace = %d", mCurrentDataSpace); - error = (*hwcLayer)->setDataspace(mCurrentDataSpace); + error = hwcLayer->setDataspace(mCurrentDataSpace); if (error != HWC2::Error::None) { ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace, to_string(error).c_str(), static_cast(error)); } const HdrMetadata& metadata = mConsumer->getCurrentHdrMetadata(); - error = (*hwcLayer)->setPerFrameMetadata(displayDevice->getSupportedPerFrameMetadata(), metadata); + error = hwcLayer->setPerFrameMetadata(displayDevice->getSupportedPerFrameMetadata(), metadata); if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) { ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), to_string(error).c_str(), static_cast(error)); @@ -671,7 +671,7 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) &hwcBuffer); auto acquireFence = mConsumer->getCurrentFence(); - error = (*hwcLayer)->setBuffer(hwcSlot, hwcBuffer, acquireFence); + error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence); if (error != HWC2::Error::None) { ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), getBE().compositionInfo.mBuffer->handle, to_string(error).c_str(), diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index e79935383e..512564c2db 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -68,7 +68,7 @@ void ColorLayer::setPerFrameData(const sp& displayDevice) { auto hwcId = displayDevice->getHwcDisplayId(); auto& hwcInfo = getBE().mHwcLayers[hwcId]; auto& hwcLayer = hwcInfo.layer; - auto error = (*hwcLayer)->setVisibleRegion(visible); + 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(error)); @@ -77,14 +77,14 @@ void ColorLayer::setPerFrameData(const sp& displayDevice) { setCompositionType(hwcId, HWC2::Composition::SolidColor); - error = (*hwcLayer)->setDataspace(mCurrentDataSpace); + error = hwcLayer->setDataspace(mCurrentDataSpace); if (error != HWC2::Error::None) { ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace, to_string(error).c_str(), static_cast(error)); } half4 color = getColor(); - error = (*hwcLayer)->setColor({static_cast(std::round(255.0f * color.r)), + error = hwcLayer->setColor({static_cast(std::round(255.0f * color.r)), static_cast(std::round(255.0f * color.g)), static_cast(std::round(255.0f * color.b)), 255}); if (error != HWC2::Error::None) { @@ -93,7 +93,7 @@ void ColorLayer::setPerFrameData(const sp& displayDevice) { } // Clear out the transform, because it doesn't make sense absent a source buffer - error = (*hwcLayer)->setTransform(HWC2::Transform::None); + 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(error)); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 13849933e8..8c1199b8a1 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -218,14 +218,15 @@ sp Layer::getHandle() { bool Layer::createHwcLayer(HWComposer* hwc, int32_t hwcId) { LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(hwcId) != 0, "Already have a layer for hwcId %d", hwcId); - - std::shared_ptr layer(new LayerContainer(hwc, hwcId)); + HWC2::Layer* layer = hwc->createLayer(hwcId); if (!layer) { return false; } LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers[hwcId]; hwcInfo.hwc = hwc; hwcInfo.layer = layer; + layer->setLayerDestroyedListener( + [this, hwcId](HWC2::Layer* /*layer*/) { getBE().mHwcLayers.erase(hwcId); }); return true; } @@ -236,12 +237,11 @@ bool Layer::destroyHwcLayer(int32_t hwcId) { 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.layer = nullptr; - - if (getBE().mHwcLayers.count(hwcId) == 1) { - getBE().mHwcLayers.erase(hwcId); - } - + hwcInfo.hwc->destroyLayer(hwcId, hwcInfo.layer); + // The layer destroyed listener should have cleared the entry from + // mHwcLayers. Verify that. + LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(hwcId) != 0, + "Stale layer entry in getBE().mHwcLayers"); return true; } @@ -500,7 +500,7 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z blendMode = mPremultipliedAlpha ? HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage; } - auto error = (*hwcLayer)->setBlendMode(blendMode); + auto error = hwcLayer->setBlendMode(blendMode); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set blend mode %s:" " %s (%d)", @@ -548,7 +548,7 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z } const Transform& tr(displayDevice->getTransform()); Rect transformedFrame = tr.transform(frame); - error = (*hwcLayer)->setDisplayFrame(transformedFrame); + 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, @@ -558,7 +558,7 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z } FloatRect sourceCrop = computeCrop(displayDevice); - error = (*hwcLayer)->setSourceCrop(sourceCrop); + error = hwcLayer->setSourceCrop(sourceCrop); if (error != HWC2::Error::None) { ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: " "%s (%d)", @@ -569,13 +569,13 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z } float alpha = static_cast(getAlpha()); - error = (*hwcLayer)->setPlaneAlpha(alpha); + 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(error)); - error = (*hwcLayer)->setZOrder(z); + 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(error)); @@ -590,7 +590,7 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z } } - error = (*hwcLayer)->setInfo(type, appId); + error = hwcLayer->setInfo(type, appId); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)", mName.string(), static_cast(error)); @@ -633,7 +633,7 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z } else { auto transform = static_cast(orientation); hwcInfo.transform = transform; - auto error = (*hwcLayer)->setTransform(transform); + auto error = hwcLayer->setTransform(transform); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set transform %s: " "%s (%d)", @@ -686,7 +686,7 @@ void Layer::updateCursorPosition(const sp& displayDevice) { auto& displayTransform(displayDevice->getTransform()); auto position = displayTransform.transform(frame); - auto error = (*getBE().mHwcLayers[hwcId].layer)->setCursorPosition(position.left, + auto error = getBE().mHwcLayers[hwcId].layer->setCursorPosition(position.left, position.top); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set cursor position " @@ -730,13 +730,13 @@ void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callI } auto& hwcInfo = getBE().mHwcLayers[hwcId]; auto& hwcLayer = hwcInfo.layer; - ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", (*hwcLayer)->getId(), to_string(type).c_str(), + ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(), to_string(type).c_str(), static_cast(callIntoHwc)); if (hwcInfo.compositionType != type) { ALOGV(" actually setting"); hwcInfo.compositionType = type; if (callIntoHwc) { - auto error = (*hwcLayer)->setCompositionType(type); + auto error = hwcLayer->setCompositionType(type); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set " "composition type %s: %s (%d)", diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 182ef8ad29..52d2de21c0 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -455,15 +455,7 @@ public: if (getBE().mHwcLayers.count(hwcId) == 0) { return nullptr; } - return *(getBE().mHwcLayers[hwcId].layer.get()); - } - - bool setHwcLayer(int32_t hwcId) { - if (getBE().mHwcLayers.count(hwcId) == 0) { - return false; - } - getBE().compositionInfo.hwc.hwcLayer = getBE().mHwcLayers[hwcId].layer; - return true; + return getBE().mHwcLayers[hwcId].layer; } // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp index 5287fe1dfd..bef051ff4d 100644 --- a/services/surfaceflinger/LayerBE.cpp +++ b/services/surfaceflinger/LayerBE.cpp @@ -35,7 +35,7 @@ void LayerBE::onLayerDisplayed(const sp& releaseFence) { } void CompositionInfo::dumpHwc(const char* tag) const { - ALOGV("[%s]\thwcLayer=%p", tag, static_cast(*hwc.hwcLayer)); + ALOGV("[%s]\thwcLayer=%p", tag, hwc.hwcLayer); ALOGV("[%s]\tfence=%p", tag, hwc.fence.get()); ALOGV("[%s]\ttransform=%d", tag, hwc.transform); ALOGV("[%s]\tz=%d", tag, hwc.z); diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 981f756664..76b9543c35 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -32,31 +32,6 @@ namespace android { class LayerBE; -class LayerContainer -{ - public: - LayerContainer(HWComposer* hwc, int32_t hwcId) : mHwc(hwc), mHwcId(hwcId) { - mLayer = hwc->createLayer(hwcId); - } - - ~LayerContainer() { - mHwc->destroyLayer(mHwcId, mLayer); - } - - HWC2::Layer* operator->() { - return mLayer; - } - - operator HWC2::Layer*const () const { - return mLayer; - } - - private: - HWComposer* mHwc; - int32_t mHwcId; - HWC2::Layer* mLayer; -}; - struct CompositionInfo { std::string layerName; HWC2::Composition compositionType; @@ -64,7 +39,7 @@ struct CompositionInfo { int mBufferSlot = BufferQueue::INVALID_BUFFER_SLOT; LayerBE* layer = nullptr; struct { - std::shared_ptr hwcLayer; + HWC2::Layer* hwcLayer; int32_t hwid = -1; sp fence; HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid; @@ -125,7 +100,7 @@ private: transform(HWC2::Transform::None) {} HWComposer* hwc; - std::shared_ptr layer; + HWC2::Layer* layer; bool forceClientComposition; HWC2::Composition compositionType; bool clearClientTarget; -- cgit v1.2.3-59-g8ed1b From eecd6597d013b2bb879bc51957ed1b5e6b61c35e Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Tue, 29 May 2018 10:25:41 -0700 Subject: SF: Use consistent names for display references This CL renames IBinder tokens to "displayToken", and DisplayDevice references to "display". It also cleans up style for affected lines. Bug: 74619554 Test: Build Change-Id: I04fc7264bf2a856caf30d662029b6f603f432938 --- services/surfaceflinger/BufferLayer.cpp | 10 +- services/surfaceflinger/BufferLayer.h | 2 +- services/surfaceflinger/ColorLayer.cpp | 8 +- services/surfaceflinger/ColorLayer.h | 2 +- services/surfaceflinger/ContainerLayer.h | 2 +- services/surfaceflinger/DisplayDevice.cpp | 4 +- services/surfaceflinger/DisplayDevice.h | 2 +- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 6 +- .../surfaceflinger/DisplayHardware/HWComposer.h | 2 +- services/surfaceflinger/Layer.cpp | 23 +- services/surfaceflinger/Layer.h | 4 +- services/surfaceflinger/SurfaceFlinger.cpp | 795 ++++++++++----------- services/surfaceflinger/SurfaceFlinger.h | 96 ++- .../tests/unittests/DisplayTransactionTest.cpp | 16 +- .../tests/unittests/TestableSurfaceFlinger.h | 12 +- 15 files changed, 452 insertions(+), 532 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index f714effdbd..2f70c45651 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -606,13 +606,13 @@ void BufferLayer::setDefaultBufferSize(uint32_t w, uint32_t h) { mConsumer->setDefaultBufferSize(w, h); } -void BufferLayer::setPerFrameData(const sp& displayDevice) { +void BufferLayer::setPerFrameData(const sp& display) { // 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(); + const Transform& tr = display->getTransform(); + const auto& viewport = display->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); - auto hwcId = displayDevice->getHwcDisplayId(); + auto hwcId = display->getHwcDisplayId(); auto& hwcInfo = getBE().mHwcLayers[hwcId]; auto& hwcLayer = hwcInfo.layer; auto error = hwcLayer->setVisibleRegion(visible); @@ -659,7 +659,7 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) } const HdrMetadata& metadata = mConsumer->getCurrentHdrMetadata(); - error = hwcLayer->setPerFrameMetadata(displayDevice->getSupportedPerFrameMetadata(), metadata); + error = hwcLayer->setPerFrameMetadata(display->getSupportedPerFrameMetadata(), metadata); if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) { ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), to_string(error).c_str(), static_cast(error)); diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 6b02f8c128..de0f746925 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -129,7 +129,7 @@ public: bool isBufferLatched() const override { return mRefreshPending; } void setDefaultBufferSize(uint32_t w, uint32_t h) override; - void setPerFrameData(const sp& displayDevice) override; + void setPerFrameData(const sp& display) override; bool isOpaque(const Layer::State& s) const override; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 512564c2db..075ab7b596 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -61,11 +61,11 @@ bool ColorLayer::isVisible() const { return !isHiddenByPolicy() && s.color.a; } -void ColorLayer::setPerFrameData(const sp& displayDevice) { - const Transform& tr = displayDevice->getTransform(); - const auto& viewport = displayDevice->getViewport(); +void ColorLayer::setPerFrameData(const sp& display) { + const Transform& tr = display->getTransform(); + const auto& viewport = display->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); - auto hwcId = displayDevice->getHwcDisplayId(); + auto hwcId = display->getHwcDisplayId(); auto& hwcInfo = getBE().mHwcLayers[hwcId]; auto& hwcLayer = hwcInfo.layer; auto error = hwcLayer->setVisibleRegion(visible); diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index 0cde398ce9..6a6e7c092f 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -34,7 +34,7 @@ public: bool useIdentityTransform) const; bool isVisible() const override; - void setPerFrameData(const sp& displayDevice) override; + void setPerFrameData(const sp& display) override; }; } // namespace android diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index 543f60a624..84b75f4f09 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -34,7 +34,7 @@ public: bool useIdentityTransform) const override; bool isVisible() const override; - void setPerFrameData(const sp& displayDevice) override; + void setPerFrameData(const sp& display) override; }; } // namespace android diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index e7d07e3856..39d0507e0a 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -436,8 +436,8 @@ int DisplayDevice::getPowerMode() const { return mPowerMode; } -bool DisplayDevice::isDisplayOn() const { - return (mPowerMode != HWC_POWER_MODE_OFF); +bool DisplayDevice::isPoweredOn() const { + return mPowerMode != HWC_POWER_MODE_OFF; } // ---------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 6d1fb16fa1..79ba15de58 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -194,7 +194,7 @@ public: */ int getPowerMode() const; void setPowerMode(int mode); - bool isDisplayOn() const; + bool isPoweredOn() const; ui::ColorMode getActiveColorMode() const; void setActiveColorMode(ui::ColorMode mode); diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 98831b3eb7..9f1e71406d 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -431,11 +431,11 @@ status_t HWComposer::setClientTarget(int32_t displayId, uint32_t slot, return NO_ERROR; } -status_t HWComposer::prepare(DisplayDevice& displayDevice) { +status_t HWComposer::prepare(DisplayDevice& display) { ATRACE_CALL(); Mutex::Autolock _l(mDisplayLock); - auto displayId = displayDevice.getHwcDisplayId(); + auto displayId = display.getHwcDisplayId(); if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { ALOGV("Skipping HWComposer prepare for non-HWC display"); return NO_ERROR; @@ -502,7 +502,7 @@ status_t HWComposer::prepare(DisplayDevice& displayDevice) { displayData.hasClientComposition = false; displayData.hasDeviceComposition = false; - for (auto& layer : displayDevice.getVisibleLayersSortedByZ()) { + for (auto& layer : display.getVisibleLayersSortedByZ()) { auto hwcLayer = layer->getHwcLayer(displayId); if (changedTypes.count(hwcLayer) != 0) { diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index c0bf198ab1..9e4a683626 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -92,7 +92,7 @@ public: void destroyLayer(int32_t displayId, HWC2::Layer* layer); // Asks the HAL what it can do - status_t prepare(DisplayDevice& displayDevice); + status_t prepare(DisplayDevice& display); status_t setClientTarget(int32_t displayId, uint32_t slot, const sp& acquireFence, diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 8c1199b8a1..60feb0de73 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -479,15 +479,14 @@ FloatRect Layer::computeCrop(const sp& hw) const { return crop; } -void Layer::setGeometry(const sp& displayDevice, uint32_t z) -{ - const auto hwcId = displayDevice->getHwcDisplayId(); +void Layer::setGeometry(const sp& display, uint32_t z) { + const auto hwcId = display->getHwcDisplayId(); auto& hwcInfo = getBE().mHwcLayers[hwcId]; // enable this layer hwcInfo.forceClientComposition = false; - if (isSecure() && !displayDevice->isSecure()) { + if (isSecure() && !display->isSecure()) { hwcInfo.forceClientComposition = true; } @@ -514,7 +513,7 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z if (!s.crop.isEmpty()) { Rect activeCrop(s.crop); activeCrop = t.transform(activeCrop); - if (!activeCrop.intersect(displayDevice->getViewport(), &activeCrop)) { + if (!activeCrop.intersect(display->getViewport(), &activeCrop)) { activeCrop.clear(); } activeCrop = t.inverse().transform(activeCrop, true); @@ -543,10 +542,10 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z frame.clear(); } } - if (!frame.intersect(displayDevice->getViewport(), &frame)) { + if (!frame.intersect(display->getViewport(), &frame)) { frame.clear(); } - const Transform& tr(displayDevice->getTransform()); + const Transform& tr = display->getTransform(); Rect transformedFrame = tr.transform(frame); error = hwcLayer->setDisplayFrame(transformedFrame); if (error != HWC2::Error::None) { @@ -557,7 +556,7 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z hwcInfo.displayFrame = transformedFrame; } - FloatRect sourceCrop = computeCrop(displayDevice); + FloatRect sourceCrop = computeCrop(display); error = hwcLayer->setSourceCrop(sourceCrop); if (error != HWC2::Error::None) { ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: " @@ -660,8 +659,8 @@ bool Layer::getForceClientComposition(int32_t hwcId) { return getBE().mHwcLayers[hwcId].forceClientComposition; } -void Layer::updateCursorPosition(const sp& displayDevice) { - auto hwcId = displayDevice->getHwcDisplayId(); +void Layer::updateCursorPosition(const sp& display) { + auto hwcId = display->getHwcDisplayId(); if (getBE().mHwcLayers.count(hwcId) == 0 || getCompositionType(hwcId) != HWC2::Composition::Cursor) { return; @@ -679,11 +678,11 @@ void Layer::updateCursorPosition(const sp& displayDevice) { // Subtract the transparent region and snap to the bounds Rect bounds = reduce(win, s.activeTransparentRegion); Rect frame(getTransform().transform(bounds)); - frame.intersect(displayDevice->getViewport(), &frame); + frame.intersect(display->getViewport(), &frame); if (!s.finalCrop.isEmpty()) { frame.intersect(s.finalCrop, &frame); } - auto& displayTransform(displayDevice->getTransform()); + auto& displayTransform = display->getTransform(); auto position = displayTransform.transform(frame); auto error = getBE().mHwcLayers[hwcId].layer->setCursorPosition(position.left, diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 52d2de21c0..5e0de88844 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -316,10 +316,10 @@ protected: public: virtual void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {} - void setGeometry(const sp& displayDevice, uint32_t z); + void setGeometry(const sp& display, uint32_t z); void forceClientComposition(int32_t hwcId); bool getForceClientComposition(int32_t hwcId); - virtual void setPerFrameData(const sp& displayDevice) = 0; + virtual void setPerFrameData(const sp& display) = 0; // callIntoHwc exists so we can update our local state and call // acceptDisplayChanges without unnecessarily updating the device's state diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 35eb8c65de..4730b7997a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -219,7 +219,7 @@ SurfaceFlinger::SurfaceFlinger(SurfaceFlinger::SkipInitializationTag) mLayersAdded(false), mRepaintEverything(0), mBootTime(systemTime()), - mBuiltinDisplays(), + mDisplayTokens(), mVisibleRegionsDirty(false), mGeometryInvalid(false), mAnimCompositionPending(false), @@ -427,12 +427,12 @@ sp SurfaceFlinger::createDisplay(const String8& displayName, return token; } -void SurfaceFlinger::destroyDisplay(const sp& display) { +void SurfaceFlinger::destroyDisplay(const sp& displayToken) { Mutex::Autolock _l(mStateLock); - ssize_t idx = mCurrentState.displays.indexOfKey(display); + ssize_t idx = mCurrentState.displays.indexOfKey(displayToken); if (idx < 0) { - ALOGW("destroyDisplay: invalid display token"); + ALOGE("destroyDisplay: Invalid display token %p", displayToken.get()); return; } @@ -451,7 +451,7 @@ sp SurfaceFlinger::getBuiltInDisplay(int32_t id) { ALOGE("getDefaultDisplay: id=%d is not a valid default display id", id); return nullptr; } - return mBuiltinDisplays[id]; + return mDisplayTokens[id]; } void SurfaceFlinger::bootFinished() @@ -808,18 +808,15 @@ status_t SurfaceFlinger::getSupportedFrameTimestamps( return NO_ERROR; } -status_t SurfaceFlinger::getDisplayConfigs(const sp& display, - Vector* configs) { - if (configs == nullptr || display.get() == nullptr) { +status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, + Vector* configs) { + if (!displayToken || !configs) { return BAD_VALUE; } - if (!display.get()) - return NAME_NOT_FOUND; - int32_t type = NAME_NOT_FOUND; - for (int i=0 ; i& display, info.density = density; // TODO: this needs to go away (currently needed only by webkit) - sp hw(getDefaultDisplayDeviceLocked()); - info.orientation = hw ? hw->getOrientation() : 0; + const auto display = getDefaultDisplayDeviceLocked(); + info.orientation = display ? display->getOrientation() : 0; } else { // TODO: where should this value come from? static const int TV_DENSITY = 213; @@ -918,9 +915,8 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& display, return NO_ERROR; } -status_t SurfaceFlinger::getDisplayStats(const sp& /* display */, - DisplayStatInfo* stats) { - if (stats == nullptr) { +status_t SurfaceFlinger::getDisplayStats(const sp&, DisplayStatInfo* stats) { + if (!stats) { return BAD_VALUE; } @@ -931,86 +927,62 @@ status_t SurfaceFlinger::getDisplayStats(const sp& /* display */, return NO_ERROR; } -int SurfaceFlinger::getActiveConfig(const sp& display) { - if (display == nullptr) { - ALOGE("%s : display is nullptr", __func__); +int SurfaceFlinger::getActiveConfig(const sp& displayToken) { + const auto display = getDisplayDevice(displayToken); + if (!display) { + ALOGE("getActiveConfig: Invalid display token %p", displayToken.get()); return BAD_VALUE; } - sp device(getDisplayDevice(display)); - if (device != nullptr) { - return device->getActiveConfig(); - } - - return BAD_VALUE; + return display->getActiveConfig(); } -void SurfaceFlinger::setActiveConfigInternal(const sp& hw, int mode) { - ALOGD("Set active config mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(), - this); - int currentMode = hw->getActiveConfig(); - +void SurfaceFlinger::setActiveConfigInternal(const sp& display, int mode) { + int currentMode = display->getActiveConfig(); if (mode == currentMode) { - ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode); return; } - if (hw->isVirtual()) { + if (display->isVirtual()) { ALOGW("Trying to set config for virtual display"); return; } - hw->setActiveConfig(mode); - getHwComposer().setActiveConfig(hw->getDisplayType(), mode); + display->setActiveConfig(mode); + getHwComposer().setActiveConfig(display->getDisplayType(), mode); } -status_t SurfaceFlinger::setActiveConfig(const sp& display, int mode) { - class MessageSetActiveConfig: public MessageBase { - SurfaceFlinger& mFlinger; - sp mDisplay; - int mMode; - public: - MessageSetActiveConfig(SurfaceFlinger& flinger, const sp& disp, - int mode) : - mFlinger(flinger), mDisplay(disp) { mMode = mode; } - virtual bool handler() { - Vector configs; - mFlinger.getDisplayConfigs(mDisplay, &configs); - if (mMode < 0 || mMode >= static_cast(configs.size())) { - ALOGE("Attempt to set active config = %d for display with %zu configs", - mMode, configs.size()); - return true; - } - sp hw(mFlinger.getDisplayDevice(mDisplay)); - if (hw == nullptr) { - ALOGE("Attempt to set active config = %d for null display %p", - mMode, mDisplay.get()); - } else if (hw->isVirtual()) { - ALOGW("Attempt to set active config = %d for virtual display", - mMode); - } else { - mFlinger.setActiveConfigInternal(hw, mMode); - } - return true; +status_t SurfaceFlinger::setActiveConfig(const sp& displayToken, int mode) { + postMessageSync(new LambdaMessage([&]() { + Vector configs; + getDisplayConfigs(displayToken, &configs); + if (mode < 0 || mode >= static_cast(configs.size())) { + ALOGE("Attempt to set active config %d for display with %zu configs", mode, + configs.size()); + return; } - }; - sp msg = new MessageSetActiveConfig(*this, display, mode); - postMessageSync(msg); + const auto display = getDisplayDevice(displayToken); + if (!display) { + ALOGE("Attempt to set active config %d for invalid display token %p", mode, + displayToken.get()); + } else if (display->isVirtual()) { + ALOGW("Attempt to set active config %d for virtual display", mode); + } else { + setActiveConfigInternal(display, mode); + } + })); + return NO_ERROR; } -status_t SurfaceFlinger::getDisplayColorModes(const sp& display, - Vector* outColorModes) { - if ((outColorModes == nullptr) || (display.get() == nullptr)) { +status_t SurfaceFlinger::getDisplayColorModes(const sp& displayToken, + Vector* outColorModes) { + if (!displayToken || !outColorModes) { return BAD_VALUE; } - if (!display.get()) { - return NAME_NOT_FOUND; - } - int32_t type = NAME_NOT_FOUND; - for (int i=0 ; i& display, return NO_ERROR; } -ColorMode SurfaceFlinger::getActiveColorMode(const sp& display) { - sp device(getDisplayDevice(display)); - if (device != nullptr) { - return device->getActiveColorMode(); +ColorMode SurfaceFlinger::getActiveColorMode(const sp& displayToken) { + if (const auto display = getDisplayDevice(displayToken)) { + return display->getActiveColorMode(); } return static_cast(BAD_VALUE); } -void SurfaceFlinger::setActiveColorModeInternal(const sp& hw, - ColorMode mode, Dataspace dataSpace, - RenderIntent renderIntent) { - ColorMode currentMode = hw->getActiveColorMode(); - Dataspace currentDataSpace = hw->getCompositionDataSpace(); - RenderIntent currentRenderIntent = hw->getActiveRenderIntent(); +void SurfaceFlinger::setActiveColorModeInternal(const sp& display, ColorMode mode, + Dataspace dataSpace, RenderIntent renderIntent) { + ColorMode currentMode = display->getActiveColorMode(); + Dataspace currentDataSpace = display->getCompositionDataSpace(); + RenderIntent currentRenderIntent = display->getActiveRenderIntent(); if (mode == currentMode && dataSpace == currentDataSpace && renderIntent == currentRenderIntent) { return; } - if (hw->isVirtual()) { + if (display->isVirtual()) { ALOGW("Trying to set config for virtual display"); return; } - hw->setActiveColorMode(mode); - hw->setCompositionDataSpace(dataSpace); - hw->setActiveRenderIntent(renderIntent); - getHwComposer().setActiveColorMode(hw->getDisplayType(), mode, renderIntent); + display->setActiveColorMode(mode); + display->setCompositionDataSpace(dataSpace); + display->setActiveRenderIntent(renderIntent); + getHwComposer().setActiveColorMode(display->getDisplayType(), mode, renderIntent); ALOGV("Set active color mode: %s (%d), active render intent: %s (%d), type=%d", - decodeColorMode(mode).c_str(), mode, - decodeRenderIntent(renderIntent).c_str(), renderIntent, - hw->getDisplayType()); -} - - -status_t SurfaceFlinger::setActiveColorMode(const sp& display, - ColorMode colorMode) { - class MessageSetActiveColorMode: public MessageBase { - SurfaceFlinger& mFlinger; - sp mDisplay; - ColorMode mMode; - public: - MessageSetActiveColorMode(SurfaceFlinger& flinger, const sp& disp, - ColorMode mode) : - mFlinger(flinger), mDisplay(disp) { mMode = mode; } - virtual bool handler() { - Vector modes; - mFlinger.getDisplayColorModes(mDisplay, &modes); - bool exists = std::find(std::begin(modes), std::end(modes), mMode) != std::end(modes); - if (mMode < ColorMode::NATIVE || !exists) { - ALOGE("Attempt to set invalid active color mode %s (%d) for display %p", - decodeColorMode(mMode).c_str(), mMode, mDisplay.get()); - return true; - } - sp hw(mFlinger.getDisplayDevice(mDisplay)); - if (hw == nullptr) { - ALOGE("Attempt to set active color mode %s (%d) for null display %p", - decodeColorMode(mMode).c_str(), mMode, mDisplay.get()); - } else if (hw->isVirtual()) { - ALOGW("Attempt to set active color mode %s %d for virtual display", - decodeColorMode(mMode).c_str(), mMode); - } else { - mFlinger.setActiveColorModeInternal(hw, mMode, Dataspace::UNKNOWN, - RenderIntent::COLORIMETRIC); - } - return true; + decodeColorMode(mode).c_str(), mode, decodeRenderIntent(renderIntent).c_str(), + renderIntent, display->getDisplayType()); +} + +status_t SurfaceFlinger::setActiveColorMode(const sp& displayToken, ColorMode mode) { + postMessageSync(new LambdaMessage([&]() { + Vector modes; + getDisplayColorModes(displayToken, &modes); + bool exists = std::find(std::begin(modes), std::end(modes), mode) != std::end(modes); + if (mode < ColorMode::NATIVE || !exists) { + ALOGE("Attempt to set invalid active color mode %s (%d) for display token %p", + decodeColorMode(mode).c_str(), mode, displayToken.get()); + return; } - }; - sp msg = new MessageSetActiveColorMode(*this, display, colorMode); - postMessageSync(msg); + const auto display = getDisplayDevice(displayToken); + if (!display) { + ALOGE("Attempt to set active color mode %s (%d) for invalid display token %p", + decodeColorMode(mode).c_str(), mode, displayToken.get()); + } else if (display->isVirtual()) { + ALOGW("Attempt to set active color mode %s (%d) for virtual display", + decodeColorMode(mode).c_str(), mode); + } else { + setActiveColorModeInternal(display, mode, Dataspace::UNKNOWN, + RenderIntent::COLORIMETRIC); + } + })); + return NO_ERROR; } @@ -1119,20 +1075,20 @@ status_t SurfaceFlinger::getAnimationFrameStats(FrameStats* outStats) const { return NO_ERROR; } -status_t SurfaceFlinger::getHdrCapabilities(const sp& display, - HdrCapabilities* outCapabilities) const { +status_t SurfaceFlinger::getHdrCapabilities(const sp& displayToken, + HdrCapabilities* outCapabilities) const { Mutex::Autolock _l(mStateLock); - sp displayDevice(getDisplayDeviceLocked(display)); - if (displayDevice == nullptr) { - ALOGE("getHdrCapabilities: Invalid display %p", displayDevice.get()); + const auto display = getDisplayDeviceLocked(displayToken); + if (!display) { + ALOGE("getHdrCapabilities: Invalid display token %p", displayToken.get()); return BAD_VALUE; } // At this point the DisplayDeivce should already be set up, // meaning the luminance information is already queried from // hardware composer and stored properly. - const HdrCapabilities& capabilities = displayDevice->getHdrCapabilities(); + const HdrCapabilities& capabilities = display->getHdrCapabilities(); *outCapabilities = HdrCapabilities(capabilities.getSupportedHdrTypes(), capabilities.getDesiredMaxLuminance(), capabilities.getDesiredMaxAverageLuminance(), @@ -1429,8 +1385,7 @@ void SurfaceFlinger::updateVrFlinger() { Mutex::Autolock _l(mStateLock); - int currentDisplayPowerMode = getDisplayDeviceLocked( - mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY])->getPowerMode(); + int currentDisplayPowerMode = getDefaultDisplayDeviceLocked()->getPowerMode(); if (!vrFlingerRequestsDisplay) { mVrFlinger->SeizeDisplayOwnership(); @@ -1455,9 +1410,8 @@ void SurfaceFlinger::updateVrFlinger() { invalidateHwcGeometry(); // Re-enable default display. - sp hw(getDisplayDeviceLocked( - mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY])); - setPowerModeInternal(hw, currentDisplayPowerMode, /*stateLockHeld*/ true); + setPowerModeInternal(getDefaultDisplayDeviceLocked(), currentDisplayPowerMode, + /*stateLockHeld*/ true); // Reset the timing values to account for the period of the swapped in HWC const auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY); @@ -1546,10 +1500,10 @@ void SurfaceFlinger::handleMessageRefresh() { mPreviousPresentFence = getBE().mHwc->getPresentFence(HWC_DISPLAY_PRIMARY); mHadClientComposition = false; - for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { - const sp& displayDevice = mDisplays[displayId]; + for (size_t i = 0; i < mDisplays.size(); ++i) { + const auto& display = mDisplays[i]; mHadClientComposition = mHadClientComposition || - getBE().mHwc->hasClientComposition(displayDevice->getHwcDisplayId()); + getBE().mHwc->hasClientComposition(display->getHwcDisplayId()); } mVsyncModulator.setLastFrameUsedRenderEngine(mHadClientComposition); @@ -1563,21 +1517,21 @@ void SurfaceFlinger::doDebugFlashRegions() return; const bool repaintEverything = mRepaintEverything; - for (size_t dpy=0 ; dpy& hw(mDisplays[dpy]); - if (hw->isDisplayOn()) { + for (size_t i = 0; i < mDisplays.size(); ++i) { + const auto& display = mDisplays[i]; + if (display->isPoweredOn()) { // transform the dirty region into this screen's coordinate space - const Region dirtyRegion(hw->getDirtyRegion(repaintEverything)); + const Region dirtyRegion = display->getDirtyRegion(repaintEverything); if (!dirtyRegion.isEmpty()) { // redraw the whole screen - doComposeSurfaces(hw); + doComposeSurfaces(display); // and draw the dirty region - const int32_t height = hw->getHeight(); + const int32_t height = display->getHeight(); auto& engine(getRenderEngine()); engine.fillRegionWithColor(dirtyRegion, height, 1, 0, 1, 1); - hw->swapBuffers(getHwComposer()); + display->swapBuffers(getHwComposer()); } } } @@ -1588,17 +1542,15 @@ void SurfaceFlinger::doDebugFlashRegions() usleep(mDebugRegion * 1000); } - for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { - auto& displayDevice = mDisplays[displayId]; - if (!displayDevice->isDisplayOn()) { + for (size_t i = 0; i < mDisplays.size(); ++i) { + const auto& display = mDisplays[i]; + if (!display->isPoweredOn()) { continue; } - status_t result = displayDevice->prepareFrame(*getBE().mHwc); - ALOGE_IF(result != NO_ERROR, - "prepareFrame for display %zd failed:" - " %d (%s)", - displayId, result, strerror(-result)); + status_t result = display->prepareFrame(*getBE().mHwc); + ALOGE_IF(result != NO_ERROR, "prepareFrame for display %d failed: %d (%s)", + display->getHwcDisplayId(), result, strerror(-result)); } } @@ -1613,10 +1565,10 @@ void SurfaceFlinger::doTracing(const char* where) { void SurfaceFlinger::logLayerStats() { ATRACE_CALL(); if (CC_UNLIKELY(mLayerStats.isEnabled())) { - for (size_t dpy = 0; dpy < mDisplays.size(); ++dpy) { - const sp& displayDevice(mDisplays[dpy]); - if (displayDevice->isPrimary()) { - mLayerStats.logLayerStats(dumpVisibleLayersProtoInfo(*displayDevice)); + for (size_t i = 0; i < mDisplays.size(); ++i) { + const auto& display = mDisplays[i]; + if (display->isPrimary()) { + mLayerStats.logLayerStats(dumpVisibleLayersProtoInfo(*display)); return; } } @@ -1713,13 +1665,13 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) } // |mStateLock| not needed as we are on the main thread - const sp hw(getDefaultDisplayDeviceLocked()); + const auto display = getDefaultDisplayDeviceLocked(); getBE().mGlCompositionDoneTimeline.updateSignalTimes(); std::shared_ptr glCompositionDoneFenceTime; - if (hw && getBE().mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) { + if (display && getBE().mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) { glCompositionDoneFenceTime = - std::make_shared(hw->getClientTargetAcquireFence()); + std::make_shared(display->getClientTargetAcquireFence()); getBE().mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime); } else { glCompositionDoneFenceTime = FenceTime::NO_FENCE; @@ -1762,7 +1714,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) } if (!hasSyncFramework) { - if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY) && hw->isDisplayOn()) { + if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY) && display->isPoweredOn()) { enableHardwareVsync(); } } @@ -1789,7 +1741,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) } if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY) && - hw->getPowerMode() == HWC_POWER_MODE_OFF) { + display->getPowerMode() == HWC_POWER_MODE_OFF) { return; } @@ -1819,21 +1771,20 @@ void SurfaceFlinger::rebuildLayerStacks() { mVisibleRegionsDirty = false; invalidateHwcGeometry(); - for (size_t dpy=0 ; dpy> layersSortedByZ; Vector> layersNeedingFences; - const sp& displayDevice(mDisplays[dpy]); - const Transform& tr(displayDevice->getTransform()); - const Rect bounds(displayDevice->getBounds()); - if (displayDevice->isDisplayOn()) { - computeVisibleRegions(displayDevice, dirtyRegion, opaqueRegion); + const auto& display = mDisplays[i]; + const Transform& tr = display->getTransform(); + const Rect bounds = display->getBounds(); + if (display->isPoweredOn()) { + computeVisibleRegions(display, dirtyRegion, opaqueRegion); mDrawingState.traverseInZOrder([&](Layer* layer) { bool hwcLayerDestroyed = false; - if (layer->belongsToDisplay(displayDevice->getLayerStack(), - displayDevice->isPrimary())) { + if (layer->belongsToDisplay(display->getLayerStack(), display->isPrimary())) { Region drawRegion(tr.transform( layer->visibleNonTransparentRegion)); drawRegion.andSelf(bounds); @@ -1842,15 +1793,13 @@ void SurfaceFlinger::rebuildLayerStacks() { } else { // Clear out the HWC layer if this layer was // previously visible, but no longer is - hwcLayerDestroyed = layer->destroyHwcLayer( - displayDevice->getHwcDisplayId()); + hwcLayerDestroyed = layer->destroyHwcLayer(display->getHwcDisplayId()); } } else { - // WM changes displayDevice->layerStack upon sleep/awake. + // WM changes display->layerStack upon sleep/awake. // Here we make sure we delete the HWC layers even if // WM changed their layer stack. - hwcLayerDestroyed = layer->destroyHwcLayer( - displayDevice->getHwcDisplayId()); + hwcLayerDestroyed = layer->destroyHwcLayer(display->getHwcDisplayId()); } // If a layer is not going to get a release fence because @@ -1866,12 +1815,11 @@ void SurfaceFlinger::rebuildLayerStacks() { } }); } - displayDevice->setVisibleLayersSortedByZ(layersSortedByZ); - displayDevice->setLayersNeedingFences(layersNeedingFences); - displayDevice->undefinedRegion.set(bounds); - displayDevice->undefinedRegion.subtractSelf( - tr.transform(opaqueRegion)); - displayDevice->dirtyRegion.orSelf(dirtyRegion); + display->setVisibleLayersSortedByZ(layersSortedByZ); + display->setLayersNeedingFences(layersNeedingFences); + display->undefinedRegion.set(bounds); + display->undefinedRegion.subtractSelf(tr.transform(opaqueRegion)); + display->dirtyRegion.orSelf(dirtyRegion); } } } @@ -1884,12 +1832,12 @@ void SurfaceFlinger::rebuildLayerStacks() { // - Dataspace::UNKNOWN // - Dataspace::BT2020_HLG // - Dataspace::BT2020_PQ -Dataspace SurfaceFlinger::getBestDataspace( - const sp& displayDevice, Dataspace* outHdrDataSpace) const { +Dataspace SurfaceFlinger::getBestDataspace(const sp& display, + Dataspace* outHdrDataSpace) const { Dataspace bestDataSpace = Dataspace::SRGB; *outHdrDataSpace = Dataspace::UNKNOWN; - for (const auto& layer : displayDevice->getVisibleLayersSortedByZ()) { + for (const auto& layer : display->getVisibleLayersSortedByZ()) { switch (layer->getDataSpace()) { case Dataspace::V0_SCRGB: case Dataspace::V0_SCRGB_LINEAR: @@ -1917,9 +1865,8 @@ Dataspace SurfaceFlinger::getBestDataspace( } // Pick the ColorMode / Dataspace for the display device. -void SurfaceFlinger::pickColorMode(const sp& displayDevice, - ColorMode* outMode, Dataspace* outDataSpace, - RenderIntent* outRenderIntent) const { +void SurfaceFlinger::pickColorMode(const sp& display, ColorMode* outMode, + Dataspace* outDataSpace, RenderIntent* outRenderIntent) const { if (mDisplayColorSetting == DisplayColorSetting::UNMANAGED) { *outMode = ColorMode::NATIVE; *outDataSpace = Dataspace::UNKNOWN; @@ -1928,11 +1875,11 @@ void SurfaceFlinger::pickColorMode(const sp& displayDevice, } Dataspace hdrDataSpace; - Dataspace bestDataSpace = getBestDataspace(displayDevice, &hdrDataSpace); + Dataspace bestDataSpace = getBestDataspace(display, &hdrDataSpace); // respect hdrDataSpace only when there is modern HDR support const bool isHdr = hdrDataSpace != Dataspace::UNKNOWN && - displayDevice->hasModernHdrSupport(hdrDataSpace); + display->hasModernHdrSupport(hdrDataSpace); if (isHdr) { bestDataSpace = hdrDataSpace; } @@ -1951,17 +1898,18 @@ void SurfaceFlinger::pickColorMode(const sp& displayDevice, break; } - displayDevice->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent); + display->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent); } void SurfaceFlinger::setUpHWComposer() { ATRACE_CALL(); ALOGV("setUpHWComposer"); - for (size_t dpy=0 ; dpygetDirtyRegion(mRepaintEverything).isEmpty(); - bool empty = mDisplays[dpy]->getVisibleLayersSortedByZ().size() == 0; - bool wasEmpty = !mDisplays[dpy]->lastCompositionHadVisibleLayers; + for (size_t i = 0; i < mDisplays.size(); ++i) { + const auto& display = mDisplays[i]; + bool dirty = !display->getDirtyRegion(mRepaintEverything).isEmpty(); + bool empty = display->getVisibleLayersSortedByZ().size() == 0; + bool wasEmpty = !display->lastCompositionHadVisibleLayers; // If nothing has changed (!dirty), don't recompose. // If something changed, but we don't currently have any visible layers, @@ -1973,29 +1921,25 @@ void SurfaceFlinger::setUpHWComposer() { // emit any black frames until a layer is added to the layer stack. bool mustRecompose = dirty && !(empty && wasEmpty); - ALOGV_IF(mDisplays[dpy]->isVirtual(), - "dpy[%zu]: %s composition (%sdirty %sempty %swasEmpty)", dpy, - mustRecompose ? "doing" : "skipping", - dirty ? "+" : "-", - empty ? "+" : "-", - wasEmpty ? "+" : "-"); + ALOGV_IF(display->isVirtual(), "Display %d: %s composition (%sdirty %sempty %swasEmpty)", + display->getHwcDisplayId(), mustRecompose ? "doing" : "skipping", + dirty ? "+" : "-", empty ? "+" : "-", wasEmpty ? "+" : "-"); - mDisplays[dpy]->beginFrame(mustRecompose); + display->beginFrame(mustRecompose); if (mustRecompose) { - mDisplays[dpy]->lastCompositionHadVisibleLayers = !empty; + display->lastCompositionHadVisibleLayers = !empty; } } // build the h/w work list if (CC_UNLIKELY(mGeometryInvalid)) { mGeometryInvalid = false; - for (size_t dpy=0 ; dpy displayDevice(mDisplays[dpy]); - const auto hwcId = displayDevice->getHwcDisplayId(); + for (size_t i = 0; i < mDisplays.size(); ++i) { + const auto& display = mDisplays[i]; + const auto hwcId = display->getHwcDisplayId(); if (hwcId >= 0) { - const Vector>& currentLayers( - displayDevice->getVisibleLayersSortedByZ()); + const Vector>& currentLayers = display->getVisibleLayersSortedByZ(); for (size_t i = 0; i < currentLayers.size(); i++) { const auto& layer = currentLayers[i]; if (!layer->hasHwcLayer(hwcId)) { @@ -2005,7 +1949,7 @@ void SurfaceFlinger::setUpHWComposer() { } } - layer->setGeometry(displayDevice, i); + layer->setGeometry(display, i); if (mDebugDisableHWC || mDebugRegion) { layer->forceClientComposition(hwcId); } @@ -2015,28 +1959,28 @@ void SurfaceFlinger::setUpHWComposer() { } // Set the per-frame data - for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { - auto& displayDevice = mDisplays[displayId]; - const auto hwcId = displayDevice->getHwcDisplayId(); + for (size_t i = 0; i < mDisplays.size(); ++i) { + const auto& display = mDisplays[i]; + const auto hwcId = display->getHwcDisplayId(); if (hwcId < 0) { continue; } if (mDrawingState.colorMatrixChanged) { - displayDevice->setColorTransform(mDrawingState.colorMatrix); + display->setColorTransform(mDrawingState.colorMatrix); status_t result = getBE().mHwc->setColorTransform(hwcId, mDrawingState.colorMatrix); - ALOGE_IF(result != NO_ERROR, "Failed to set color transform on " - "display %zd: %d", displayId, result); + ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display %d: %d", + display->getHwcDisplayId(), result); } - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { + for (auto& layer : display->getVisibleLayersSortedByZ()) { if ((layer->getDataSpace() == Dataspace::BT2020_PQ || layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) && - !displayDevice->hasHDR10Support()) { + !display->hasHDR10Support()) { layer->forceClientComposition(hwcId); } if ((layer->getDataSpace() == Dataspace::BT2020_HLG || layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) && - !displayDevice->hasHLGSupport()) { + !display->hasHLGSupport()) { layer->forceClientComposition(hwcId); } @@ -2046,29 +1990,29 @@ void SurfaceFlinger::setUpHWComposer() { continue; } - layer->setPerFrameData(displayDevice); + layer->setPerFrameData(display); } if (hasWideColorDisplay) { ColorMode colorMode; Dataspace dataSpace; RenderIntent renderIntent; - pickColorMode(displayDevice, &colorMode, &dataSpace, &renderIntent); - setActiveColorModeInternal(displayDevice, colorMode, dataSpace, renderIntent); + pickColorMode(display, &colorMode, &dataSpace, &renderIntent); + setActiveColorModeInternal(display, colorMode, dataSpace, renderIntent); } } mDrawingState.colorMatrixChanged = false; - for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { - auto& displayDevice = mDisplays[displayId]; - if (!displayDevice->isDisplayOn()) { + for (size_t i = 0; i < mDisplays.size(); ++i) { + const auto& display = mDisplays[i]; + if (!display->isPoweredOn()) { continue; } - status_t result = displayDevice->prepareFrame(*getBE().mHwc); - ALOGE_IF(result != NO_ERROR, "prepareFrame for display %zd failed:" - " %d (%s)", displayId, result, strerror(-result)); + status_t result = display->prepareFrame(*getBE().mHwc); + ALOGE_IF(result != NO_ERROR, "prepareFrame for display %d failed: %d (%s)", + display->getHwcDisplayId(), result, strerror(-result)); } } @@ -2077,17 +2021,17 @@ void SurfaceFlinger::doComposition() { ALOGV("doComposition"); const bool repaintEverything = android_atomic_and(0, &mRepaintEverything); - for (size_t dpy=0 ; dpy& hw(mDisplays[dpy]); - if (hw->isDisplayOn()) { + for (size_t i = 0; i < mDisplays.size(); ++i) { + const auto& display = mDisplays[i]; + if (display->isPoweredOn()) { // transform the dirty region into this screen's coordinate space - const Region dirtyRegion(hw->getDirtyRegion(repaintEverything)); + const Region dirtyRegion = display->getDirtyRegion(repaintEverything); // repaint the framebuffer (if needed) - doDisplayComposition(hw, dirtyRegion); + doDisplayComposition(display, dirtyRegion); - hw->dirtyRegion.clear(); - hw->flip(); + display->dirtyRegion.clear(); + display->flip(); } } postFramebuffer(); @@ -2101,18 +2045,18 @@ void SurfaceFlinger::postFramebuffer() const nsecs_t now = systemTime(); mDebugInSwapBuffers = now; - for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { - auto& displayDevice = mDisplays[displayId]; - if (!displayDevice->isDisplayOn()) { + for (size_t i = 0; i < mDisplays.size(); ++i) { + const auto& display = mDisplays[i]; + if (!display->isPoweredOn()) { continue; } - const auto hwcId = displayDevice->getHwcDisplayId(); + const auto hwcId = display->getHwcDisplayId(); if (hwcId >= 0) { getBE().mHwc->presentAndGetReleaseFences(hwcId); } - displayDevice->onSwapBuffersCompleted(); - displayDevice->makeCurrent(); - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { + display->onSwapBuffersCompleted(); + display->makeCurrent(); + for (auto& layer : display->getVisibleLayersSortedByZ()) { // The layer buffer from the previous frame (if any) is released // by HWC only when the release fence from this frame (if any) is // signaled. Always get the release fence from HWC first. @@ -2126,18 +2070,18 @@ void SurfaceFlinger::postFramebuffer() // this is suboptimal. if (layer->getCompositionType(hwcId) == HWC2::Composition::Client) { releaseFence = Fence::merge("LayerRelease", releaseFence, - displayDevice->getClientTargetAcquireFence()); + display->getClientTargetAcquireFence()); } layer->getBE().onLayerDisplayed(releaseFence); } // We've got a list of layers needing fences, that are disjoint with - // displayDevice->getVisibleLayersSortedByZ. The best we can do is to + // display->getVisibleLayersSortedByZ. The best we can do is to // supply them with the present fence. - if (!displayDevice->getLayersNeedingFences().isEmpty()) { + if (!display->getLayersNeedingFences().isEmpty()) { sp presentFence = getBE().mHwc->getPresentFence(hwcId); - for (auto& layer : displayDevice->getLayersNeedingFences()) { + for (auto& layer : display->getLayersNeedingFences()) { layer->getBE().onLayerDisplayed(presentFence); } } @@ -2235,27 +2179,27 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { } if (event.connection == HWC2::Connection::Connected) { - if (!mBuiltinDisplays[displayType].get()) { + if (!mDisplayTokens[displayType].get()) { ALOGV("Creating built in display %d", displayType); - mBuiltinDisplays[displayType] = new BBinder(); + mDisplayTokens[displayType] = new BBinder(); DisplayDeviceState info; info.type = displayType; info.displayName = displayType == DisplayDevice::DISPLAY_PRIMARY ? "Built-in Screen" : "External Screen"; info.isSecure = true; // All physical displays are currently considered secure. - mCurrentState.displays.add(mBuiltinDisplays[displayType], info); + mCurrentState.displays.add(mDisplayTokens[displayType], info); mInterceptor->saveDisplayCreation(info); } } else { ALOGV("Removing built in display %d", displayType); - ssize_t idx = mCurrentState.displays.indexOfKey(mBuiltinDisplays[displayType]); + ssize_t idx = mCurrentState.displays.indexOfKey(mDisplayTokens[displayType]); if (idx >= 0) { const DisplayDeviceState& info(mCurrentState.displays.valueAt(idx)); mInterceptor->saveDisplayDeletion(info.sequenceId); mCurrentState.displays.removeItemsAt(idx); } - mBuiltinDisplays[displayType].clear(); + mDisplayTokens[displayType].clear(); } processDisplayChangesLocked(); @@ -2265,7 +2209,7 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { } sp SurfaceFlinger::setupNewDisplayDeviceInternal( - const wp& display, int hwcId, const DisplayDeviceState& state, + const wp& displayToken, int hwcId, const DisplayDeviceState& state, const sp& dispSurface, const sp& producer) { bool hasWideColorGamut = false; std::unordered_map> hwcColorModes; @@ -2319,12 +2263,12 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( // virtual displays are always considered enabled auto initialPowerMode = state.isVirtual() ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF; - sp hw = - new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow, + sp display = + new DisplayDevice(this, state.type, hwcId, state.isSecure, displayToken, nativeWindow, dispSurface, std::move(renderSurface), displayWidth, displayHeight, hasWideColorGamut, hdrCapabilities, - getHwComposer().getSupportedPerFrameMetadata(hwcId), - hwcColorModes, initialPowerMode); + getHwComposer().getSupportedPerFrameMetadata(hwcId), hwcColorModes, + initialPowerMode); if (maxFrameBufferAcquiredBuffers >= 3) { nativeWindowSurface->preallocateBuffers(); @@ -2336,16 +2280,16 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( defaultColorMode = ColorMode::SRGB; defaultDataSpace = Dataspace::SRGB; } - setActiveColorModeInternal(hw, defaultColorMode, defaultDataSpace, + setActiveColorModeInternal(display, defaultColorMode, defaultDataSpace, RenderIntent::COLORIMETRIC); if (state.type < DisplayDevice::DISPLAY_VIRTUAL) { - hw->setActiveConfig(getHwComposer().getActiveConfigIndex(state.type)); + display->setActiveConfig(getHwComposer().getActiveConfigIndex(state.type)); } - hw->setLayerStack(state.layerStack); - hw->setProjection(state.orientation, state.viewport, state.frame); - hw->setDisplayName(state.displayName); + display->setLayerStack(state.layerStack); + display->setProjection(state.orientation, state.viewport, state.frame); + display->setDisplayName(state.displayName); - return hw; + return display; } void SurfaceFlinger::processDisplayChangesLocked() { @@ -2370,17 +2314,19 @@ void SurfaceFlinger::processDisplayChangesLocked() { // Call makeCurrent() on the primary display so we can // be sure that nothing associated with this display // is current. - const sp defaultDisplay(getDefaultDisplayDeviceLocked()); - if (defaultDisplay != nullptr) defaultDisplay->makeCurrent(); - sp hw(getDisplayDeviceLocked(draw.keyAt(i))); - if (hw != nullptr) hw->disconnect(getHwComposer()); + if (const auto defaultDisplay = getDefaultDisplayDeviceLocked()) { + defaultDisplay->makeCurrent(); + } + if (const auto display = getDisplayDeviceLocked(draw.keyAt(i))) { + display->disconnect(getHwComposer()); + } if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) mEventThread->onHotplugReceived(draw[i].type, false); mDisplays.removeItem(draw.keyAt(i)); } else { // this display is in both lists. see if something changed. const DisplayDeviceState& state(curr[j]); - const wp& display(curr.keyAt(j)); + const wp& displayToken = curr.keyAt(j); const sp state_binder = IInterface::asBinder(state.surface); const sp draw_binder = IInterface::asBinder(draw[i].surface); if (state_binder != draw_binder) { @@ -2388,26 +2334,26 @@ void SurfaceFlinger::processDisplayChangesLocked() { // recreating the DisplayDevice, so we just remove it // from the drawing state, so that it get re-added // below. - sp hw(getDisplayDeviceLocked(display)); - if (hw != nullptr) hw->disconnect(getHwComposer()); - mDisplays.removeItem(display); + if (const auto display = getDisplayDeviceLocked(displayToken)) { + display->disconnect(getHwComposer()); + } + mDisplays.removeItem(displayToken); mDrawingState.displays.removeItemsAt(i); dc--; // at this point we must loop to the next item continue; } - const sp disp(getDisplayDeviceLocked(display)); - if (disp != nullptr) { + if (const auto display = getDisplayDeviceLocked(displayToken)) { if (state.layerStack != draw[i].layerStack) { - disp->setLayerStack(state.layerStack); + display->setLayerStack(state.layerStack); } if ((state.orientation != draw[i].orientation) || (state.viewport != draw[i].viewport) || (state.frame != draw[i].frame)) { - disp->setProjection(state.orientation, state.viewport, state.frame); + display->setProjection(state.orientation, state.viewport, state.frame); } if (state.width != draw[i].width || state.height != draw[i].height) { - disp->setDisplaySize(state.width, state.height); + display->setDisplaySize(state.width, state.height); } } } @@ -2469,11 +2415,11 @@ void SurfaceFlinger::processDisplayChangesLocked() { producer = bqProducer; } - const wp& display(curr.keyAt(i)); + const wp& displayToken = curr.keyAt(i); if (dispSurface != nullptr) { - mDisplays.add(display, - setupNewDisplayDeviceInternal(display, hwcId, state, dispSurface, - producer)); + mDisplays.add(displayToken, + setupNewDisplayDeviceInternal(displayToken, hwcId, state, + dispSurface, producer)); if (!state.isVirtual()) { mEventThread->onHotplugReceived(state.type, true); } @@ -2537,7 +2483,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // happened yet, so we must use the current state layer list // (soon to become the drawing state list). // - sp disp; + sp display; uint32_t currentlayerStack = 0; bool first = true; mCurrentState.traverseInZOrder([&](Layer* layer) { @@ -2550,34 +2496,34 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // figure out if this layerstack is mirrored // (more than one display) if so, pick the default display, // if not, pick the only display it's on. - disp.clear(); - for (size_t dpy=0 ; dpy hw(mDisplays[dpy]); - if (layer->belongsToDisplay(hw->getLayerStack(), hw->isPrimary())) { - if (disp == nullptr) { - disp = std::move(hw); - } else { - disp = nullptr; + display = nullptr; + for (size_t i = 0; i < mDisplays.size(); ++i) { + if (layer->belongsToDisplay(mDisplays[i]->getLayerStack(), + mDisplays[i]->isPrimary())) { + if (display) { + display = nullptr; break; + } else { + display = mDisplays[i]; } } } } - if (disp == nullptr) { + if (!display) { // NOTE: TEMPORARY FIX ONLY. Real fix should cause layers to // redraw after transform hint changes. See bug 8508397. // could be null when this layer is using a layerStack // that is not visible on any display. Also can occur at // screen off/on times. - disp = getDefaultDisplayDeviceLocked(); + display = getDefaultDisplayDeviceLocked(); } // disp can be null if there is no display available at all to get // the transform hint from. - if (disp != nullptr) { - layer->updateTransformHint(disp); + if (display) { + layer->updateTransformHint(display); } first = false; @@ -2620,14 +2566,14 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) void SurfaceFlinger::updateCursorAsync() { - for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { - auto& displayDevice = mDisplays[displayId]; - if (displayDevice->getHwcDisplayId() < 0) { + for (size_t i = 0; i < mDisplays.size(); ++i) { + const auto& display = mDisplays[i]; + if (display->getHwcDisplayId() < 0) { continue; } - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - layer->updateCursorPosition(displayDevice); + for (auto& layer : display->getVisibleLayersSortedByZ()) { + layer->updateCursorPosition(display); } } } @@ -2660,9 +2606,8 @@ void SurfaceFlinger::commitTransaction() mTransactionCV.broadcast(); } -void SurfaceFlinger::computeVisibleRegions(const sp& displayDevice, - Region& outDirtyRegion, Region& outOpaqueRegion) -{ +void SurfaceFlinger::computeVisibleRegions(const sp& display, + Region& outDirtyRegion, Region& outOpaqueRegion) { ATRACE_CALL(); ALOGV("computeVisibleRegions"); @@ -2677,8 +2622,9 @@ void SurfaceFlinger::computeVisibleRegions(const sp& displa const Layer::State& s(layer->getDrawingState()); // only consider the layers on the given layer stack - if (!layer->belongsToDisplay(displayDevice->getLayerStack(), displayDevice->isPrimary())) + if (!layer->belongsToDisplay(display->getLayerStack(), display->isPrimary())) { return; + } /* * opaqueRegion: area of a surface that is fully opaque. @@ -2798,10 +2744,10 @@ void SurfaceFlinger::computeVisibleRegions(const sp& displa } void SurfaceFlinger::invalidateLayerStack(const sp& layer, const Region& dirty) { - for (size_t dpy=0 ; dpy& hw(mDisplays[dpy]); - if (layer->belongsToDisplay(hw->getLayerStack(), hw->isPrimary())) { - hw->dirtyRegion.orSelf(dirty); + for (size_t i = 0; i < mDisplays.size(); ++i) { + const auto& display = mDisplays[i]; + if (layer->belongsToDisplay(display->getLayerStack(), display->isPrimary())) { + display->dirtyRegion.orSelf(dirty); } } } @@ -2865,35 +2811,31 @@ void SurfaceFlinger::invalidateHwcGeometry() mGeometryInvalid = true; } - -void SurfaceFlinger::doDisplayComposition( - const sp& displayDevice, - const Region& inDirtyRegion) -{ +void SurfaceFlinger::doDisplayComposition(const sp& display, + const Region& inDirtyRegion) { // We only need to actually compose the display if: // 1) It is being handled by hardware composer, which may need this to // keep its virtual display state machine in sync, or // 2) There is work to be done (the dirty region isn't empty) - bool isHwcDisplay = displayDevice->getHwcDisplayId() >= 0; + bool isHwcDisplay = display->getHwcDisplayId() >= 0; if (!isHwcDisplay && inDirtyRegion.isEmpty()) { ALOGV("Skipping display composition"); return; } ALOGV("doDisplayComposition"); - if (!doComposeSurfaces(displayDevice)) return; + if (!doComposeSurfaces(display)) return; // swap buffers (presentation) - displayDevice->swapBuffers(getHwComposer()); + display->swapBuffers(getHwComposer()); } -bool SurfaceFlinger::doComposeSurfaces(const sp& displayDevice) -{ +bool SurfaceFlinger::doComposeSurfaces(const sp& display) { ALOGV("doComposeSurfaces"); - const Region bounds(displayDevice->bounds()); - const DisplayRenderArea renderArea(displayDevice); - const auto hwcId = displayDevice->getHwcDisplayId(); + const Region bounds(display->bounds()); + const DisplayRenderArea renderArea(display); + const auto hwcId = display->getHwcDisplayId(); const bool hasClientComposition = getBE().mHwc->hasClientComposition(hwcId); ATRACE_INT("hasClientComposition", hasClientComposition); @@ -2905,12 +2847,12 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev ALOGV("hasClientComposition"); Dataspace outputDataspace = Dataspace::UNKNOWN; - if (displayDevice->hasWideColorGamut()) { - outputDataspace = displayDevice->getCompositionDataSpace(); + if (display->hasWideColorGamut()) { + outputDataspace = display->getCompositionDataSpace(); } getBE().mRenderEngine->setOutputDataSpace(outputDataspace); getBE().mRenderEngine->setDisplayMaxLuminance( - displayDevice->getHdrCapabilities().getDesiredMaxLuminance()); + display->getHdrCapabilities().getDesiredMaxLuminance()); const bool hasDeviceComposition = getBE().mHwc->hasDeviceComposition(hwcId); const bool skipClientColorTransform = getBE().mHwc->hasCapability( @@ -2922,13 +2864,12 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev } needsLegacyColorMatrix = - (displayDevice->getActiveRenderIntent() >= RenderIntent::ENHANCE && - outputDataspace != Dataspace::UNKNOWN && - outputDataspace != Dataspace::SRGB); + (display->getActiveRenderIntent() >= RenderIntent::ENHANCE && + outputDataspace != Dataspace::UNKNOWN && outputDataspace != Dataspace::SRGB); - if (!displayDevice->makeCurrent()) { + if (!display->makeCurrent()) { ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s", - displayDevice->getDisplayName().c_str()); + display->getDisplayName().c_str()); getRenderEngine().resetCurrentSurface(); // |mStateLock| not needed as we are on the main thread @@ -2950,31 +2891,31 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev // we start with the whole screen area and remove the scissor part // we're left with the letterbox region // (common case is that letterbox ends-up being empty) - const Region letterbox(bounds.subtract(displayDevice->getScissor())); + const Region letterbox = bounds.subtract(display->getScissor()); // compute the area to clear - Region region(displayDevice->undefinedRegion.merge(letterbox)); + const Region region = display->undefinedRegion.merge(letterbox); // screen is already cleared here if (!region.isEmpty()) { // can happen with SurfaceView - drawWormhole(displayDevice, region); + drawWormhole(display, region); } } - if (!displayDevice->isPrimary()) { + if (!display->isPrimary()) { // just to be on the safe side, we don't set the // scissor on the main display. It should never be needed // anyways (though in theory it could since the API allows it). - const Rect& bounds(displayDevice->getBounds()); - const Rect& scissor(displayDevice->getScissor()); + const Rect& bounds = display->getBounds(); + const Rect& scissor = display->getScissor(); if (scissor != bounds) { // scissor doesn't match the screen's dimensions, so we // need to clear everything outside of it and enable // the GL scissor so we don't draw anything where we shouldn't // enable scissor for this frame - const uint32_t height = displayDevice->getHeight(); + const uint32_t height = display->getHeight(); getBE().mRenderEngine->setScissor(scissor.left, height - scissor.bottom, scissor.getWidth(), scissor.getHeight()); } @@ -2986,9 +2927,9 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev */ ALOGV("Rendering client layers"); - const Transform& displayTransform = displayDevice->getTransform(); + const Transform& displayTransform = display->getTransform(); bool firstLayer = true; - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { + for (auto& layer : display->getVisibleLayersSortedByZ()) { const Region clip(bounds.intersect( displayTransform.transform(layer->visibleRegion))); ALOGV("Layer: %s", layer->getName().string()); @@ -3046,8 +2987,9 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev return true; } -void SurfaceFlinger::drawWormhole(const sp& displayDevice, const Region& region) const { - const int32_t height = displayDevice->getHeight(); +void SurfaceFlinger::drawWormhole(const sp& display, + const Region& region) const { + const int32_t height = display->getHeight(); auto& engine(getRenderEngine()); engine.fillRegionWithColor(region, height, 0, 0, 0, 0); } @@ -3657,7 +3599,7 @@ void SurfaceFlinger::onInitializeDisplays() { DisplayState d; d.what = DisplayState::eDisplayProjectionChanged | DisplayState::eLayerStackChanged; - d.token = mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]; + d.token = mDisplayTokens[DisplayDevice::DISPLAY_PRIMARY]; d.layerStack = 0; d.orientation = DisplayState::eOrientationDefault; d.frame.makeInvalid(); @@ -3692,25 +3634,26 @@ void SurfaceFlinger::initializeDisplays() { postMessageAsync(msg); // we may be called from main thread, use async message } -void SurfaceFlinger::setPowerModeInternal(const sp& hw, - int mode, bool stateLockHeld) { - ALOGD("Set power mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(), - this); - int currentMode = hw->getPowerMode(); +void SurfaceFlinger::setPowerModeInternal(const sp& display, int mode, + bool stateLockHeld) { + const int32_t displayId = display->getHwcDisplayId(); + ALOGD("Setting power mode %d on display %d", mode, displayId); + int currentMode = display->getPowerMode(); if (mode == currentMode) { return; } - hw->setPowerMode(mode); - if (hw->isVirtual()) { + if (display->isVirtual()) { ALOGW("Trying to set power mode for virtual display"); return; } + display->setPowerMode(mode); + if (mInterceptor->isEnabled()) { ConditionalLock lock(mStateLock, !stateLockHeld); - ssize_t idx = mCurrentState.displays.indexOfKey(hw->getDisplayToken()); + ssize_t idx = mCurrentState.displays.indexOfKey(display->getDisplayToken()); if (idx < 0) { ALOGW("Surface Interceptor SavePowerMode: invalid display token"); return; @@ -3718,11 +3661,11 @@ void SurfaceFlinger::setPowerModeInternal(const sp& hw, mInterceptor->savePowerModeUpdate(mCurrentState.displays.valueAt(idx).sequenceId, mode); } - int32_t type = hw->getDisplayType(); + int32_t type = display->getDisplayType(); if (currentMode == HWC_POWER_MODE_OFF) { // Turn on the display getHwComposer().setPowerMode(type, mode); - if (hw->isPrimary() && mode != HWC_POWER_MODE_DOZE_SUSPEND) { + if (display->isPrimary() && mode != HWC_POWER_MODE_DOZE_SUSPEND) { // FIXME: eventthread only knows about the main display right now mEventThread->onScreenAcquired(); resyncToHardwareVsync(true); @@ -3744,7 +3687,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp& hw, ALOGW("Couldn't set SCHED_OTHER on display off"); } - if (hw->isPrimary() && currentMode != HWC_POWER_MODE_DOZE_SUSPEND) { + if (display->isPrimary() && currentMode != HWC_POWER_MODE_DOZE_SUSPEND) { disableHardwareVsync(true); // also cancels any in-progress resync // FIXME: eventthread only knows about the main display right now @@ -3758,14 +3701,14 @@ void SurfaceFlinger::setPowerModeInternal(const sp& hw, mode == HWC_POWER_MODE_NORMAL) { // Update display while dozing getHwComposer().setPowerMode(type, mode); - if (hw->isPrimary() && currentMode == HWC_POWER_MODE_DOZE_SUSPEND) { + if (display->isPrimary() && currentMode == HWC_POWER_MODE_DOZE_SUSPEND) { // FIXME: eventthread only knows about the main display right now mEventThread->onScreenAcquired(); resyncToHardwareVsync(true); } } else if (mode == HWC_POWER_MODE_DOZE_SUSPEND) { // Leave display going to doze - if (hw->isPrimary()) { + if (display->isPrimary()) { disableHardwareVsync(true); // also cancels any in-progress resync // FIXME: eventthread only knows about the main display right now mEventThread->onScreenReleased(); @@ -3775,35 +3718,22 @@ void SurfaceFlinger::setPowerModeInternal(const sp& hw, ALOGE("Attempting to set unknown power mode: %d\n", mode); getHwComposer().setPowerMode(type, mode); } - ALOGD("Finished set power mode=%d, type=%d", mode, hw->getDisplayType()); + + ALOGD("Finished setting power mode %d on display %d", mode, displayId); } -void SurfaceFlinger::setPowerMode(const sp& display, int mode) { - class MessageSetPowerMode: public MessageBase { - SurfaceFlinger& mFlinger; - sp mDisplay; - int mMode; - public: - MessageSetPowerMode(SurfaceFlinger& flinger, - const sp& disp, int mode) : mFlinger(flinger), - mDisplay(disp) { mMode = mode; } - virtual bool handler() { - sp hw(mFlinger.getDisplayDevice(mDisplay)); - if (hw == nullptr) { - ALOGE("Attempt to set power mode = %d for null display %p", - mMode, mDisplay.get()); - } else if (hw->isVirtual()) { - ALOGW("Attempt to set power mode = %d for virtual display", - mMode); - } else { - mFlinger.setPowerModeInternal( - hw, mMode, /*stateLockHeld*/ false); - } - return true; +void SurfaceFlinger::setPowerMode(const sp& displayToken, int mode) { + postMessageSync(new LambdaMessage([&]() { + const auto display = getDisplayDevice(displayToken); + if (!display) { + ALOGE("Attempt to set power mode %d for invalid display token %p", mode, + displayToken.get()); + } else if (display->isVirtual()) { + ALOGW("Attempt to set power mode %d for virtual display", mode); + } else { + setPowerModeInternal(display, mode, /*stateLockHeld*/ false); } - }; - sp msg = new MessageSetPowerMode(*this, display, mode); - postMessageSync(msg); + })); } // --------------------------------------------------------------------------- @@ -4100,9 +4030,9 @@ void SurfaceFlinger::dumpBufferingStats(String8& result) const { } void SurfaceFlinger::dumpDisplayIdentificationData(String8& result) const { - for (size_t d = 0; d < mDisplays.size(); d++) { - const sp& displayDevice(mDisplays[d]); - const int32_t hwcId = displayDevice->getHwcDisplayId(); + for (size_t i = 0; i < mDisplays.size(); ++i) { + const auto& display = mDisplays[i]; + const int32_t hwcId = display->getHwcDisplayId(); const auto displayId = getHwComposer().getHwcDisplayId(hwcId); if (!displayId) { continue; @@ -4149,9 +4079,9 @@ void SurfaceFlinger::dumpWideColorInfo(String8& result) const { // TODO: print out if wide-color mode is active or not - for (size_t d = 0; d < mDisplays.size(); d++) { - const sp& displayDevice(mDisplays[d]); - int32_t hwcId = displayDevice->getHwcDisplayId(); + for (size_t i = 0; i < mDisplays.size(); ++i) { + const auto& display = mDisplays[i]; + const int32_t hwcId = display->getHwcDisplayId(); if (hwcId == DisplayDevice::DISPLAY_ID_INVALID) { continue; } @@ -4162,7 +4092,7 @@ void SurfaceFlinger::dumpWideColorInfo(String8& result) const { result.appendFormat(" %s (%d)\n", decodeColorMode(mode).c_str(), mode); } - ColorMode currentMode = displayDevice->getActiveColorMode(); + ColorMode currentMode = display->getActiveColorMode(); result.appendFormat(" Current color mode: %s (%d)\n", decodeColorMode(currentMode).c_str(), currentMode); } @@ -4181,18 +4111,18 @@ LayersProto SurfaceFlinger::dumpProtoInfo(LayerVector::StateSet stateSet) const return layersProto; } -LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(const DisplayDevice& displayDevice) const { +LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(const DisplayDevice& display) const { LayersProto layersProto; SizeProto* resolution = layersProto.mutable_resolution(); - resolution->set_w(displayDevice.getWidth()); - resolution->set_h(displayDevice.getHeight()); + resolution->set_w(display.getWidth()); + resolution->set_h(display.getHeight()); - layersProto.set_color_mode(decodeColorMode(displayDevice.getActiveColorMode())); - layersProto.set_color_transform(decodeColorTransform(displayDevice.getColorTransform())); - layersProto.set_global_transform(static_cast(displayDevice.getOrientationTransform())); + layersProto.set_color_mode(decodeColorMode(display.getActiveColorMode())); + layersProto.set_color_transform(decodeColorTransform(display.getColorTransform())); + layersProto.set_global_transform(static_cast(display.getOrientationTransform())); - const int32_t hwcId = displayDevice.getHwcDisplayId(); + const int32_t hwcId = display.getHwcDisplayId(); mDrawingState.traverseInZOrder([&](Layer* layer) { if (!layer->visibleRegion.isEmpty() && layer->getBE().mHwcLayers.count(hwcId)) { LayerProto* layerProto = layersProto.add_layers(); @@ -4287,9 +4217,9 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, colorizer.bold(result); result.appendFormat("Displays (%zu entries)\n", mDisplays.size()); colorizer.reset(result); - for (size_t dpy=0 ; dpy& hw(mDisplays[dpy]); - hw->dump(result); + for (size_t i = 0; i < mDisplays.size(); ++i) { + const auto& display = mDisplays[i]; + display->dump(result); } result.append("\n"); @@ -4302,14 +4232,14 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, colorizer.reset(result); HWComposer& hwc(getHwComposer()); - sp hw(getDefaultDisplayDeviceLocked()); + const auto display = getDefaultDisplayDeviceLocked(); getBE().mRenderEngine->dump(result); - if (hw) { - hw->undefinedRegion.dump(result, "undefinedRegion"); - result.appendFormat(" orientation=%d, isDisplayOn=%d\n", - hw->getOrientation(), hw->isDisplayOn()); + if (display) { + display->undefinedRegion.dump(result, "undefinedRegion"); + result.appendFormat(" orientation=%d, isPoweredOn=%d\n", display->getOrientation(), + display->isPoweredOn()); } result.appendFormat( " last eglSwapBuffers() time: %f us\n" @@ -4343,9 +4273,9 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, /* * HWC layer minidump */ - for (size_t d = 0; d < mDisplays.size(); d++) { - const sp& displayDevice(mDisplays[d]); - int32_t hwcId = displayDevice->getHwcDisplayId(); + for (size_t i = 0; i < mDisplays.size(); ++i) { + const auto& display = mDisplays[i]; + const int32_t hwcId = display->getHwcDisplayId(); if (hwcId == DisplayDevice::DISPLAY_ID_INVALID) { continue; } @@ -4388,19 +4318,19 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, const Vector< sp >& SurfaceFlinger::getLayerSortedByZForHwcDisplay(int id) { // Note: mStateLock is held here - wp dpy; - for (size_t i=0 ; i displayToken; + for (size_t i = 0; i < mDisplays.size(); ++i) { if (mDisplays.valueAt(i)->getHwcDisplayId() == id) { - dpy = mDisplays.keyAt(i); + displayToken = mDisplays.keyAt(i); break; } } - if (dpy == nullptr) { + if (displayToken == nullptr) { ALOGE("getLayerSortedByZForHwcDisplay: invalid hwc display id %d", id); // Just use the primary display so we have something to return - dpy = getBuiltInDisplay(DisplayDevice::DISPLAY_PRIMARY); + displayToken = getBuiltInDisplay(DisplayDevice::DISPLAY_PRIMARY); } - return getDisplayDeviceLocked(dpy)->getVisibleLayersSortedByZ(); + return getDisplayDeviceLocked(displayToken)->getVisibleLayersSortedByZ(); } bool SurfaceFlinger::startDdmConnection() @@ -4574,8 +4504,8 @@ status_t SurfaceFlinger::onTransact( reply->writeInt32(mDebugDisableHWC); return NO_ERROR; case 1013: { - sp hw(getDefaultDisplayDevice()); - reply->writeInt32(hw->getPageFlipCount()); + const auto display = getDefaultDisplayDevice(); + reply->writeInt32(display->getPageFlipCount()); return NO_ERROR; } case 1014: { @@ -4706,8 +4636,8 @@ status_t SurfaceFlinger::onTransact( } // Is a DisplayColorSetting supported? case 1027: { - sp hw(getDefaultDisplayDevice()); - if (!hw) { + const auto display = getDefaultDisplayDevice(); + if (!display) { return NAME_NOT_FOUND; } @@ -4720,10 +4650,11 @@ status_t SurfaceFlinger::onTransact( reply->writeBool(true); break; case DisplayColorSetting::ENHANCED: - reply->writeBool(hw->hasRenderIntent(RenderIntent::ENHANCE)); + reply->writeBool(display->hasRenderIntent(RenderIntent::ENHANCE)); break; default: // vendor display color setting - reply->writeBool(hw->hasRenderIntent(static_cast(setting))); + reply->writeBool( + display->hasRenderIntent(static_cast(setting))); break; } return NO_ERROR; @@ -4751,22 +4682,22 @@ private: const int mApi; }; -status_t SurfaceFlinger::captureScreen(const sp& display, sp* outBuffer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, +status_t SurfaceFlinger::captureScreen(const sp& displayToken, + sp* outBuffer, Rect sourceCrop, + uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ, + int32_t maxLayerZ, bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { ATRACE_CALL(); - if (CC_UNLIKELY(display == 0)) return BAD_VALUE; + if (!displayToken) return BAD_VALUE; - const sp device(getDisplayDeviceLocked(display)); - if (CC_UNLIKELY(device == 0)) return BAD_VALUE; + const auto display = getDisplayDeviceLocked(displayToken); + if (!display) return BAD_VALUE; - DisplayRenderArea renderArea(device, sourceCrop, reqHeight, reqWidth, rotation); + DisplayRenderArea renderArea(display, sourceCrop, reqHeight, reqWidth, rotation); auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this, - device, minLayerZ, maxLayerZ, std::placeholders::_1); + display, minLayerZ, maxLayerZ, std::placeholders::_1); return captureScreenCommon(renderArea, traverseLayers, outBuffer, useIdentityTransform); } @@ -5164,13 +5095,13 @@ void SurfaceFlinger::State::traverseInReverseZOrder(const LayerVector::Visitor& layersSortedByZ.traverseInReverseZOrder(stateSet, visitor); } -void SurfaceFlinger::traverseLayersInDisplay(const sp& hw, int32_t minLayerZ, - int32_t maxLayerZ, +void SurfaceFlinger::traverseLayersInDisplay(const sp& display, + int32_t minLayerZ, int32_t maxLayerZ, const LayerVector::Visitor& visitor) { // We loop through the first level of layers without traversing, // as we need to interpret min/max layer Z in the top level Z space. for (const auto& layer : mDrawingState.layersSortedByZ) { - if (!layer->belongsToDisplay(hw->getLayerStack(), false)) { + if (!layer->belongsToDisplay(display->getLayerStack(), false)) { continue; } const Layer::State& state(layer->getDrawingState()); @@ -5179,7 +5110,7 @@ void SurfaceFlinger::traverseLayersInDisplay(const sp& hw, continue; } layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { - if (!layer->belongsToDisplay(hw->getLayerStack(), false)) { + if (!layer->belongsToDisplay(display->getLayerStack(), false)) { return; } if (!layer->isVisible()) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 750f2ec39d..88abaa19e9 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -408,7 +408,7 @@ private: virtual sp createConnection(); virtual sp createScopedConnection(const sp& gbp); virtual sp createDisplay(const String8& displayName, bool secure); - virtual void destroyDisplay(const sp& display); + virtual void destroyDisplay(const sp& displayToken); virtual sp getBuiltInDisplay(int32_t id); virtual void setTransactionState(const Vector& state, const Vector& displays, uint32_t flags); @@ -419,27 +419,26 @@ private: std::vector* outSupported) const; virtual sp createDisplayEventConnection( ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp); - virtual status_t captureScreen(const sp& display, sp* outBuffer, + virtual status_t captureScreen(const sp& displayToken, sp* outBuffer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, ISurfaceComposer::Rotation rotation); virtual status_t captureLayers(const sp& parentHandle, sp* outBuffer, const Rect& sourceCrop, float frameScale, bool childrenOnly); - virtual status_t getDisplayStats(const sp& display, - DisplayStatInfo* stats); - virtual status_t getDisplayConfigs(const sp& display, - Vector* configs); - virtual int getActiveConfig(const sp& display); - virtual status_t getDisplayColorModes(const sp& display, - Vector* configs); - virtual ui::ColorMode getActiveColorMode(const sp& display); - virtual status_t setActiveColorMode(const sp& display, ui::ColorMode colorMode); - virtual void setPowerMode(const sp& display, int mode); - virtual status_t setActiveConfig(const sp& display, int id); + virtual status_t getDisplayStats(const sp& displayToken, DisplayStatInfo* stats); + virtual status_t getDisplayConfigs(const sp& displayToken, + Vector* configs); + virtual int getActiveConfig(const sp& displayToken); + virtual status_t getDisplayColorModes(const sp& displayToken, + Vector* configs); + virtual ui::ColorMode getActiveColorMode(const sp& displayToken); + virtual status_t setActiveColorMode(const sp& displayToken, ui::ColorMode colorMode); + virtual void setPowerMode(const sp& displayToken, int mode); + virtual status_t setActiveConfig(const sp& displayToken, int id); virtual status_t clearAnimationFrameStats(); virtual status_t getAnimationFrameStats(FrameStats* outStats) const; - virtual status_t getHdrCapabilities(const sp& display, - HdrCapabilities* outCapabilities) const; + virtual status_t getHdrCapabilities(const sp& displayToken, + HdrCapabilities* outCapabilities) const; virtual status_t enableVSyncInjections(bool enable); virtual status_t injectVSync(nsecs_t when); virtual status_t getLayerDebugInfo(std::vector* outLayers) const; @@ -477,16 +476,13 @@ private: // called on the main thread in response to initializeDisplays() void onInitializeDisplays(); // called on the main thread in response to setActiveConfig() - void setActiveConfigInternal(const sp& hw, int mode); + void setActiveConfigInternal(const sp& display, int mode); // called on the main thread in response to setPowerMode() - void setPowerModeInternal(const sp& hw, int mode, - bool stateLockHeld); + void setPowerModeInternal(const sp& display, int mode, bool stateLockHeld); // Called on the main thread in response to setActiveColorMode() - void setActiveColorModeInternal(const sp& hw, - ui::ColorMode colorMode, - ui::Dataspace dataSpace, - ui::RenderIntent renderIntent); + void setActiveColorModeInternal(const sp& display, ui::ColorMode colorMode, + ui::Dataspace dataSpace, ui::RenderIntent renderIntent); // Returns whether the transaction actually modified any state bool handleMessageTransaction(); @@ -597,38 +593,32 @@ private: // called when starting, or restarting after system_server death void initializeDisplays(); - sp getDisplayDevice(const wp& dpy) const { - Mutex::Autolock _l(mStateLock); - return getDisplayDeviceLocked(dpy); + sp getDisplayDevice(const wp& displayToken) const { + Mutex::Autolock _l(mStateLock); + return getDisplayDeviceLocked(displayToken); } - sp getDisplayDevice(const wp& dpy) { - Mutex::Autolock _l(mStateLock); - return getDisplayDeviceLocked(dpy); + sp getDisplayDevice(const wp& displayToken) { + Mutex::Autolock _l(mStateLock); + return getDisplayDeviceLocked(displayToken); } // NOTE: can only be called from the main thread or with mStateLock held - sp getDisplayDeviceLocked(const wp& dpy) const { - return mDisplays.valueFor(dpy); + sp getDisplayDeviceLocked(const wp& displayToken) const { + return const_cast(this)->getDisplayDeviceLocked(displayToken); } // NOTE: can only be called from the main thread or with mStateLock held - sp getDisplayDeviceLocked(const wp& dpy) { - return mDisplays.valueFor(dpy); + sp getDisplayDeviceLocked(const wp& displayToken) { + return mDisplays.valueFor(displayToken); } sp getDefaultDisplayDeviceLocked() const { - return getDisplayDeviceLocked(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]); + return const_cast(this)->getDefaultDisplayDeviceLocked(); } - int32_t getDisplayType(const sp& display) { - if (!display.get()) return NAME_NOT_FOUND; - for (int i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; ++i) { - if (display == mBuiltinDisplays[i]) { - return i; - } - } - return NAME_NOT_FOUND; + sp getDefaultDisplayDeviceLocked() { + return getDisplayDeviceLocked(mDisplayTokens[DisplayDevice::DISPLAY_PRIMARY]); } // mark a region of a layer stack dirty. this updates the dirty @@ -645,8 +635,8 @@ private: * Compositing */ void invalidateHwcGeometry(); - void computeVisibleRegions(const sp& displayDevice, - Region& dirtyRegion, Region& opaqueRegion); + void computeVisibleRegions(const sp& display, Region& dirtyRegion, + Region& opaqueRegion); void preComposition(nsecs_t refreshStartTime); void postComposition(nsecs_t refreshStartTime); @@ -658,37 +648,35 @@ private: nsecs_t compositeToPresentLatency); void rebuildLayerStacks(); - ui::Dataspace getBestDataspace(const sp& displayDevice, + ui::Dataspace getBestDataspace(const sp& display, ui::Dataspace* outHdrDataSpace) const; // Returns the appropriate ColorMode, Dataspace and RenderIntent for the // DisplayDevice. The function only returns the supported ColorMode, // Dataspace and RenderIntent. - void pickColorMode(const sp& displayDevice, - ui::ColorMode* outMode, - ui::Dataspace* outDataSpace, - ui::RenderIntent* outRenderIntent) const; + void pickColorMode(const sp& display, ui::ColorMode* outMode, + ui::Dataspace* outDataSpace, ui::RenderIntent* outRenderIntent) const; void setUpHWComposer(); void doComposition(); void doDebugFlashRegions(); void doTracing(const char* where); void logLayerStats(); - void doDisplayComposition(const sp& displayDevice, const Region& dirtyRegion); + void doDisplayComposition(const sp& display, const Region& dirtyRegion); // compose surfaces for display hw. this fails if using GL and the surface // has been destroyed and is no longer valid. - bool doComposeSurfaces(const sp& displayDevice); + bool doComposeSurfaces(const sp& display); void postFramebuffer(); - void drawWormhole(const sp& displayDevice, const Region& region) const; + void drawWormhole(const sp& display, const Region& region) const; /* ------------------------------------------------------------------------ * Display management */ DisplayDevice::DisplayType determineDisplayType(hwc2_display_t display, HWC2::Connection connection) const; - sp setupNewDisplayDeviceInternal(const wp& display, int hwcId, + sp setupNewDisplayDeviceInternal(const wp& displayToken, int hwcId, const DisplayDeviceState& state, const sp& dispSurface, const sp& producer); @@ -741,7 +729,7 @@ private: void dumpDisplayIdentificationData(String8& result) const; void dumpWideColorInfo(String8& result) const; LayersProto dumpProtoInfo(LayerVector::StateSet stateSet) const; - LayersProto dumpVisibleLayersProtoInfo(const DisplayDevice& displayDevice) const; + LayersProto dumpVisibleLayersProtoInfo(const DisplayDevice& display) const; bool isLayerTripleBufferingDisabled() const { return this->mLayerTripleBufferingDisabled; @@ -797,7 +785,7 @@ private: std::unique_ptr mSfEventThreadSource; std::unique_ptr mVSyncInjector; std::unique_ptr mEventControlThread; - sp mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES]; + sp mDisplayTokens[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES]; VSyncModulator mVsyncModulator; diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index 662143889a..1364c079b1 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -1202,7 +1202,7 @@ void HandleTransactionLockedTest::verifyPhysicalDisplayIsConnected() { static_assert(0 <= Case::Display::TYPE && Case::Display::TYPE < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES, "Must use a valid physical display type index for the fixed-size array"); - auto& displayToken = mFlinger.mutableBuiltinDisplays()[Case::Display::TYPE]; + auto& displayToken = mFlinger.mutableDisplayTokens()[Case::Display::TYPE]; ASSERT_TRUE(displayToken != nullptr); verifyDisplayIsConnected(displayToken); @@ -1308,7 +1308,7 @@ void HandleTransactionLockedTest::processesHotplugDisconnectCommon() { // The display should not be set up as a built-in display. ASSERT_TRUE(0 <= Case::Display::TYPE && Case::Display::TYPE < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES); - auto displayToken = mFlinger.mutableBuiltinDisplays()[Case::Display::TYPE]; + auto displayToken = mFlinger.mutableDisplayTokens()[Case::Display::TYPE]; EXPECT_TRUE(displayToken == nullptr); // The existing token should have been removed @@ -1401,7 +1401,7 @@ TEST_F(HandleTransactionLockedTest, processesHotplugConnectThenDisconnectPrimary // The display should not be set up as a primary built-in display. ASSERT_TRUE(0 <= Case::Display::TYPE && Case::Display::TYPE < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES); - auto displayToken = mFlinger.mutableBuiltinDisplays()[Case::Display::TYPE]; + auto displayToken = mFlinger.mutableDisplayTokens()[Case::Display::TYPE]; EXPECT_TRUE(displayToken == nullptr); } @@ -1444,7 +1444,7 @@ TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectThenConnectPrimary static_assert(0 <= Case::Display::TYPE && Case::Display::TYPE < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES, "Display type must be a built-in display"); - EXPECT_NE(existing.token(), mFlinger.mutableBuiltinDisplays()[Case::Display::TYPE]); + EXPECT_NE(existing.token(), mFlinger.mutableDisplayTokens()[Case::Display::TYPE]); // A new display should be connected in its place @@ -2698,7 +2698,7 @@ TEST_F(SetPowerModeInternalTest, setPowerModeInternalDoesNothingIfNoChange) { EXPECT_EQ(HWC_POWER_MODE_NORMAL, display.mutableDisplayDevice()->getPowerMode()); } -TEST_F(SetPowerModeInternalTest, setPowerModeInternalJustSetsInternalStateIfVirtualDisplay) { +TEST_F(SetPowerModeInternalTest, setPowerModeInternalDoesNothingIfVirtualDisplay) { using Case = HwcVirtualDisplayCase; // -------------------------------------------------------------------- @@ -2713,13 +2713,13 @@ TEST_F(SetPowerModeInternalTest, setPowerModeInternalJustSetsInternalStateIfVirt auto display = Case::Display::makeFakeExistingDisplayInjector(this); display.inject(); - // The display is set to HWC_POWER_MODE_OFF - getDisplayDevice(display.token())->setPowerMode(HWC_POWER_MODE_OFF); + // The display is set to HWC_POWER_MODE_NORMAL + getDisplayDevice(display.token())->setPowerMode(HWC_POWER_MODE_NORMAL); // -------------------------------------------------------------------- // Invocation - mFlinger.setPowerModeInternal(display.mutableDisplayDevice(), HWC_POWER_MODE_NORMAL); + mFlinger.setPowerModeInternal(display.mutableDisplayDevice(), HWC_POWER_MODE_OFF); // -------------------------------------------------------------------- // Postconditions diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 5fb66fe325..5497d032bf 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -64,15 +64,17 @@ public: return mFlinger->createDisplay(displayName, secure); } - auto destroyDisplay(const sp& display) { return mFlinger->destroyDisplay(display); } + auto destroyDisplay(const sp& displayToken) { + return mFlinger->destroyDisplay(displayToken); + } auto resetDisplayState() { return mFlinger->resetDisplayState(); } - auto setupNewDisplayDeviceInternal(const wp& display, int hwcId, + auto setupNewDisplayDeviceInternal(const wp& displayToken, int hwcId, const DisplayDeviceState& state, const sp& dispSurface, const sp& producer) { - return mFlinger->setupNewDisplayDeviceInternal(display, hwcId, state, dispSurface, + return mFlinger->setupNewDisplayDeviceInternal(displayToken, hwcId, state, dispSurface, producer); } @@ -111,7 +113,7 @@ public: auto& mutableHasWideColorDisplay() { return SurfaceFlinger::hasWideColorDisplay; } - auto& mutableBuiltinDisplays() { return mFlinger->mBuiltinDisplays; } + auto& mutableDisplayTokens() { return mFlinger->mDisplayTokens; } auto& mutableCurrentState() { return mFlinger->mCurrentState; } auto& mutableDisplays() { return mFlinger->mDisplays; } auto& mutableDisplayColorSetting() { return mFlinger->mDisplayColorSetting; } @@ -312,7 +314,7 @@ public: mFlinger.mutableDrawingState().displays.add(mDisplayToken, state); if (mType >= DisplayDevice::DISPLAY_PRIMARY && mType < DisplayDevice::DISPLAY_VIRTUAL) { - mFlinger.mutableBuiltinDisplays()[mType] = mDisplayToken; + mFlinger.mutableDisplayTokens()[mType] = mDisplayToken; } return device; -- cgit v1.2.3-59-g8ed1b From 7e045460d345a3bf2b62f9dcb2eb794ab6ba2a28 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Wed, 30 May 2018 13:02:02 -0700 Subject: SF: Use consistent names for display IDs There are two types of display IDs: hwc2_display_t for HWC IDs, and int32_t for SF IDs. The latter are confusingly referred to as "hwcId". This CL renames them to "hwcDisplayId" and "displayId", respectively. Note that int32_t will be replaced by DisplayId in a follow-up CL. Bug: 74619554 Test: Build Change-Id: Ia9b621d385c2bf842a2093b578140dc7a2eaea69 --- services/surfaceflinger/BufferLayer.cpp | 14 +- services/surfaceflinger/ColorLayer.cpp | 6 +- services/surfaceflinger/DisplayDevice.cpp | 22 +-- services/surfaceflinger/DisplayDevice.h | 6 +- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 8 +- services/surfaceflinger/Layer.cpp | 90 +++++------ services/surfaceflinger/Layer.h | 30 ++-- services/surfaceflinger/LayerBE.h | 1 - services/surfaceflinger/SurfaceFlinger.cpp | 173 ++++++++++----------- services/surfaceflinger/SurfaceFlinger.h | 3 +- .../tests/unittests/DisplayTransactionTest.cpp | 8 +- .../tests/unittests/TestableSurfaceFlinger.h | 18 +-- 12 files changed, 186 insertions(+), 193 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 2f70c45651..0b0654cf86 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -612,8 +612,8 @@ void BufferLayer::setPerFrameData(const sp& display) { const Transform& tr = display->getTransform(); const auto& viewport = display->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); - auto hwcId = display->getHwcDisplayId(); - auto& hwcInfo = getBE().mHwcLayers[hwcId]; + const auto displayId = display->getId(); + auto& hwcInfo = getBE().mHwcLayers[displayId]; auto& hwcLayer = hwcInfo.layer; auto error = hwcLayer->setVisibleRegion(visible); if (error != HWC2::Error::None) { @@ -631,7 +631,7 @@ void BufferLayer::setPerFrameData(const sp& display) { // Sideband layers if (getBE().compositionInfo.hwc.sidebandStream.get()) { - setCompositionType(hwcId, HWC2::Composition::Sideband); + setCompositionType(displayId, HWC2::Composition::Sideband); ALOGV("[%s] Requesting Sideband composition", mName.string()); error = hwcLayer->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle()); if (error != HWC2::Error::None) { @@ -645,10 +645,10 @@ void BufferLayer::setPerFrameData(const sp& display) { // Device or Cursor layers if (mPotentialCursor) { ALOGV("[%s] Requesting Cursor composition", mName.string()); - setCompositionType(hwcId, HWC2::Composition::Cursor); + setCompositionType(displayId, HWC2::Composition::Cursor); } else { ALOGV("[%s] Requesting Device composition", mName.string()); - setCompositionType(hwcId, HWC2::Composition::Device); + setCompositionType(displayId, HWC2::Composition::Device); } ALOGV("setPerFrameData: dataspace = %d", mCurrentDataSpace); @@ -667,8 +667,8 @@ void BufferLayer::setPerFrameData(const sp& display) { uint32_t hwcSlot = 0; sp hwcBuffer; - getBE().mHwcLayers[hwcId].bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, &hwcSlot, - &hwcBuffer); + getBE().mHwcLayers[displayId].bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, + &hwcSlot, &hwcBuffer); auto acquireFence = mConsumer->getCurrentFence(); error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence); diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 075ab7b596..ab8afb644b 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -65,8 +65,8 @@ void ColorLayer::setPerFrameData(const sp& display) { const Transform& tr = display->getTransform(); const auto& viewport = display->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); - auto hwcId = display->getHwcDisplayId(); - auto& hwcInfo = getBE().mHwcLayers[hwcId]; + const auto displayId = display->getId(); + auto& hwcInfo = getBE().mHwcLayers[displayId]; auto& hwcLayer = hwcInfo.layer; auto error = hwcLayer->setVisibleRegion(visible); if (error != HWC2::Error::None) { @@ -75,7 +75,7 @@ void ColorLayer::setPerFrameData(const sp& display) { visible.dump(LOG_TAG); } - setCompositionType(hwcId, HWC2::Composition::SolidColor); + setCompositionType(displayId, HWC2::Composition::SolidColor); error = hwcLayer->setDataspace(mCurrentDataSpace); if (error != HWC2::Error::None) { diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 39d0507e0a..d2ef5a2a42 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -216,7 +216,7 @@ RenderIntent getHwcRenderIntent(const std::vector& hwcIntents, Ren DisplayDevice::DisplayDevice( const sp& flinger, DisplayType type, - int32_t hwcId, + int32_t id, bool isSecure, const wp& displayToken, const sp& nativeWindow, @@ -232,7 +232,7 @@ DisplayDevice::DisplayDevice( : lastCompositionHadVisibleLayers(false), mFlinger(flinger), mType(type), - mHwcDisplayId(hwcId), + mId(id), mDisplayToken(displayToken), mNativeWindow(nativeWindow), mDisplaySurface(displaySurface), @@ -301,9 +301,9 @@ DisplayDevice::DisplayDevice( DisplayDevice::~DisplayDevice() = default; void DisplayDevice::disconnect(HWComposer& hwc) { - if (mHwcDisplayId >= 0) { - hwc.disconnectDisplay(mHwcDisplayId); - mHwcDisplayId = -1; + if (mId >= 0) { + hwc.disconnectDisplay(mId); + mId = -1; } } @@ -347,8 +347,8 @@ status_t DisplayDevice::prepareFrame(HWComposer& hwc) { } DisplaySurface::CompositionType compositionType; - bool hasClient = hwc.hasClientComposition(mHwcDisplayId); - bool hasDevice = hwc.hasDeviceComposition(mHwcDisplayId); + bool hasClient = hwc.hasClientComposition(mId); + bool hasDevice = hwc.hasDeviceComposition(mId); if (hasClient && hasDevice) { compositionType = DisplaySurface::COMPOSITION_MIXED; } else if (hasClient) { @@ -365,7 +365,7 @@ status_t DisplayDevice::prepareFrame(HWComposer& hwc) { } void DisplayDevice::swapBuffers(HWComposer& hwc) const { - if (hwc.hasClientComposition(mHwcDisplayId) || hwc.hasFlipClientTargetRequest(mHwcDisplayId)) { + if (hwc.hasClientComposition(mId) || hwc.hasFlipClientTargetRequest(mId)) { mSurface->swapBuffers(); } @@ -660,10 +660,10 @@ void DisplayDevice::dump(String8& result) const { const Transform& tr(mGlobalTransform); ANativeWindow* const window = mNativeWindow.get(); result.appendFormat("+ DisplayDevice: %s\n", mDisplayName.c_str()); - result.appendFormat(" type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p " + result.appendFormat(" type=%x, ID=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p " "(%d:%d:%d:%d), orient=%2d (type=%08x), " "flips=%u, isSecure=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n", - mType, mHwcDisplayId, mLayerStack, mDisplayWidth, mDisplayHeight, window, + mType, mId, mLayerStack, mDisplayWidth, mDisplayHeight, window, mSurface->queryRedSize(), mSurface->queryGreenSize(), mSurface->queryBlueSize(), mSurface->queryAlphaSize(), mOrientation, tr.getType(), getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig, @@ -703,7 +703,7 @@ void DisplayDevice::addColorMode( const Dataspace dataspace = colorModeToDataspace(mode); const Dataspace hwcDataspace = colorModeToDataspace(hwcColorMode); - ALOGV("DisplayDevice %d/%d: map (%s, %s) to (%s, %s, %s)", mType, mHwcDisplayId, + ALOGV("DisplayDevice %d/%d: map (%s, %s) to (%s, %s, %s)", mType, mId, dataspaceDetails(static_cast(dataspace)).c_str(), decodeRenderIntent(intent).c_str(), dataspaceDetails(static_cast(hwcDataspace)).c_str(), diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 79ba15de58..93377a2fa0 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -81,7 +81,7 @@ public: DisplayDevice( const sp& flinger, DisplayType type, - int32_t hwcId, + int32_t id, bool isSecure, const wp& displayToken, const sp& nativeWindow, @@ -136,7 +136,7 @@ public: int32_t getDisplayType() const { return mType; } bool isPrimary() const { return mType == DISPLAY_PRIMARY; } bool isVirtual() const { return mType == DISPLAY_VIRTUAL; } - int32_t getHwcDisplayId() const { return mHwcDisplayId; } + int32_t getId() const { return mId; } const wp& getDisplayToken() const { return mDisplayToken; } int32_t getSupportedPerFrameMetadata() const { return mSupportedPerFrameMetadata; } @@ -226,7 +226,7 @@ private: */ sp mFlinger; DisplayType mType; - int32_t mHwcDisplayId; + int32_t mId; wp mDisplayToken; // ANativeWindow this display is rendering into diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 9f1e71406d..cd0635af48 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -435,7 +435,7 @@ status_t HWComposer::prepare(DisplayDevice& display) { ATRACE_CALL(); Mutex::Autolock _l(mDisplayLock); - auto displayId = display.getHwcDisplayId(); + const auto displayId = display.getId(); if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { ALOGV("Skipping HWComposer prepare for non-HWC display"); return NO_ERROR; @@ -723,11 +723,11 @@ void HWComposer::disconnectDisplay(int displayId) { ++mRemainingHwcVirtualDisplays; } - auto hwcId = displayData.hwcDisplay->getId(); - mHwcDisplaySlots.erase(hwcId); + const auto hwcDisplayId = displayData.hwcDisplay->getId(); + mHwcDisplaySlots.erase(hwcDisplayId); displayData.reset(); - mHwcDevice->destroyDisplay(hwcId); + mHwcDevice->destroyDisplay(hwcDisplayId); } status_t HWComposer::setOutputBuffer(int32_t displayId, diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 60feb0de73..de8cf68c88 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -215,32 +215,32 @@ sp Layer::getHandle() { // h/w composer set-up // --------------------------------------------------------------------------- -bool Layer::createHwcLayer(HWComposer* hwc, int32_t hwcId) { - LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(hwcId) != 0, - "Already have a layer for hwcId %d", hwcId); - HWC2::Layer* layer = hwc->createLayer(hwcId); +bool Layer::createHwcLayer(HWComposer* hwc, int32_t displayId) { + LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(displayId) != 0, + "Already have a layer for display %d", displayId); + HWC2::Layer* layer = hwc->createLayer(displayId); if (!layer) { return false; } - LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers[hwcId]; + LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers[displayId]; hwcInfo.hwc = hwc; hwcInfo.layer = layer; layer->setLayerDestroyedListener( - [this, hwcId](HWC2::Layer* /*layer*/) { getBE().mHwcLayers.erase(hwcId); }); + [this, displayId](HWC2::Layer* /*layer*/) { getBE().mHwcLayers.erase(displayId); }); return true; } -bool Layer::destroyHwcLayer(int32_t hwcId) { - if (getBE().mHwcLayers.count(hwcId) == 0) { +bool Layer::destroyHwcLayer(int32_t displayId) { + if (getBE().mHwcLayers.count(displayId) == 0) { return false; } - auto& hwcInfo = getBE().mHwcLayers[hwcId]; + auto& hwcInfo = getBE().mHwcLayers[displayId]; 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); + hwcInfo.hwc->destroyLayer(displayId, hwcInfo.layer); // The layer destroyed listener should have cleared the entry from // mHwcLayers. Verify that. - LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(hwcId) != 0, + LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(displayId) != 0, "Stale layer entry in getBE().mHwcLayers"); return true; } @@ -480,8 +480,8 @@ FloatRect Layer::computeCrop(const sp& hw) const { } void Layer::setGeometry(const sp& display, uint32_t z) { - const auto hwcId = display->getHwcDisplayId(); - auto& hwcInfo = getBE().mHwcLayers[hwcId]; + const auto displayId = display->getId(); + auto& hwcInfo = getBE().mHwcLayers[displayId]; // enable this layer hwcInfo.forceClientComposition = false; @@ -641,28 +641,28 @@ void Layer::setGeometry(const sp& display, uint32_t z) { } } -void Layer::forceClientComposition(int32_t hwcId) { - if (getBE().mHwcLayers.count(hwcId) == 0) { - ALOGE("forceClientComposition: no HWC layer found (%d)", hwcId); +void Layer::forceClientComposition(int32_t displayId) { + if (getBE().mHwcLayers.count(displayId) == 0) { + ALOGE("forceClientComposition: no HWC layer found (%d)", displayId); return; } - getBE().mHwcLayers[hwcId].forceClientComposition = true; + getBE().mHwcLayers[displayId].forceClientComposition = true; } -bool Layer::getForceClientComposition(int32_t hwcId) { - if (getBE().mHwcLayers.count(hwcId) == 0) { - ALOGE("getForceClientComposition: no HWC layer found (%d)", hwcId); +bool Layer::getForceClientComposition(int32_t displayId) { + if (getBE().mHwcLayers.count(displayId) == 0) { + ALOGE("getForceClientComposition: no HWC layer found (%d)", displayId); return false; } - return getBE().mHwcLayers[hwcId].forceClientComposition; + return getBE().mHwcLayers[displayId].forceClientComposition; } void Layer::updateCursorPosition(const sp& display) { - auto hwcId = display->getHwcDisplayId(); - if (getBE().mHwcLayers.count(hwcId) == 0 || - getCompositionType(hwcId) != HWC2::Composition::Cursor) { + const auto displayId = display->getId(); + if (getBE().mHwcLayers.count(displayId) == 0 || + getCompositionType(displayId) != HWC2::Composition::Cursor) { return; } @@ -685,8 +685,8 @@ void Layer::updateCursorPosition(const sp& display) { auto& displayTransform = display->getTransform(); auto position = displayTransform.transform(frame); - auto error = getBE().mHwcLayers[hwcId].layer->setCursorPosition(position.left, - position.top); + auto error = + getBE().mHwcLayers[displayId].layer->setCursorPosition(position.left, position.top); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set cursor position " "to (%d, %d): %s (%d)", @@ -722,12 +722,12 @@ void Layer::clearWithOpenGL(const RenderArea& renderArea) const { clearWithOpenGL(renderArea, 0, 0, 0, 0); } -void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc) { - if (getBE().mHwcLayers.count(hwcId) == 0) { +void Layer::setCompositionType(int32_t displayId, HWC2::Composition type, bool callIntoHwc) { + if (getBE().mHwcLayers.count(displayId) == 0) { ALOGE("setCompositionType called without a valid HWC layer"); return; } - auto& hwcInfo = getBE().mHwcLayers[hwcId]; + auto& hwcInfo = getBE().mHwcLayers[displayId]; auto& hwcLayer = hwcInfo.layer; ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(), to_string(type).c_str(), static_cast(callIntoHwc)); @@ -745,33 +745,33 @@ void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callI } } -HWC2::Composition Layer::getCompositionType(int32_t hwcId) const { - if (hwcId == DisplayDevice::DISPLAY_ID_INVALID) { +HWC2::Composition Layer::getCompositionType(int32_t displayId) const { + if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { // If we're querying the composition type for a display that does not // have a HWC counterpart, then it will always be Client return HWC2::Composition::Client; } - if (getBE().mHwcLayers.count(hwcId) == 0) { + if (getBE().mHwcLayers.count(displayId) == 0) { ALOGE("getCompositionType called with an invalid HWC layer"); return HWC2::Composition::Invalid; } - return getBE().mHwcLayers.at(hwcId).compositionType; + return getBE().mHwcLayers.at(displayId).compositionType; } -void Layer::setClearClientTarget(int32_t hwcId, bool clear) { - if (getBE().mHwcLayers.count(hwcId) == 0) { +void Layer::setClearClientTarget(int32_t displayId, bool clear) { + if (getBE().mHwcLayers.count(displayId) == 0) { ALOGE("setClearClientTarget called without a valid HWC layer"); return; } - getBE().mHwcLayers[hwcId].clearClientTarget = clear; + getBE().mHwcLayers[displayId].clearClientTarget = clear; } -bool Layer::getClearClientTarget(int32_t hwcId) const { - if (getBE().mHwcLayers.count(hwcId) == 0) { +bool Layer::getClearClientTarget(int32_t displayId) const { + if (getBE().mHwcLayers.count(displayId) == 0) { ALOGE("getClearClientTarget called without a valid HWC layer"); return false; } - return getBE().mHwcLayers.at(hwcId).clearClientTarget; + return getBE().mHwcLayers.at(displayId).clearClientTarget; } bool Layer::addSyncPoint(const std::shared_ptr& point) { @@ -1452,8 +1452,8 @@ void Layer::miniDumpHeader(String8& result) { result.append("---------------------------------------\n"); } -void Layer::miniDump(String8& result, int32_t hwcId) const { - if (getBE().mHwcLayers.count(hwcId) == 0) { +void Layer::miniDump(String8& result, int32_t displayId) const { + if (getBE().mHwcLayers.count(displayId) == 0) { return; } @@ -1471,13 +1471,13 @@ void Layer::miniDump(String8& result, int32_t hwcId) const { result.appendFormat(" %s\n", name.string()); const Layer::State& layerState(getDrawingState()); - const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(hwcId); + const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(displayId); 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()); + result.appendFormat("%10s | ", to_string(getCompositionType(displayId)).c_str()); const Rect& frame = hwcInfo.displayFrame; result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom); const FloatRect& crop = hwcInfo.sourceCrop; @@ -1975,10 +1975,10 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) layerInfo->set_app_id(state.appId); } -void Layer::writeToProto(LayerProto* layerInfo, int32_t hwcId) { +void Layer::writeToProto(LayerProto* layerInfo, int32_t displayId) { writeToProto(layerInfo, LayerVector::StateSet::Drawing); - const auto& hwcInfo = getBE().mHwcLayers.at(hwcId); + const auto& hwcInfo = getBE().mHwcLayers.at(displayId); const Rect& frame = hwcInfo.displayFrame; LayerProtoHelper::writeToProto(frame, layerInfo->mutable_hwc_frame()); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 5e0de88844..c521d5d5b5 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -304,7 +304,7 @@ public: void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing); - void writeToProto(LayerProto* layerInfo, int32_t hwcId); + void writeToProto(LayerProto* layerInfo, int32_t displayId); protected: /* @@ -317,16 +317,16 @@ public: virtual void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {} void setGeometry(const sp& display, uint32_t z); - void forceClientComposition(int32_t hwcId); - bool getForceClientComposition(int32_t hwcId); + void forceClientComposition(int32_t displayId); + bool getForceClientComposition(int32_t displayId); virtual void setPerFrameData(const sp& display) = 0; // 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); - HWC2::Composition getCompositionType(int32_t hwcId) const; - void setClearClientTarget(int32_t hwcId, bool clear); - bool getClearClientTarget(int32_t hwcId) const; + void setCompositionType(int32_t displayId, HWC2::Composition type, bool callIntoHwc = true); + HWC2::Composition getCompositionType(int32_t displayId) const; + void setClearClientTarget(int32_t displayId, bool clear); + bool getClearClientTarget(int32_t displayId) const; void updateCursorPosition(const sp& hw); /* @@ -443,19 +443,17 @@ public: // ----------------------------------------------------------------------- - bool createHwcLayer(HWComposer* hwc, int32_t hwcId); - bool destroyHwcLayer(int32_t hwcId); + bool createHwcLayer(HWComposer* hwc, int32_t displayId); + bool destroyHwcLayer(int32_t displayId); void destroyAllHwcLayers(); - bool hasHwcLayer(int32_t hwcId) { - return getBE().mHwcLayers.count(hwcId) > 0; - } + bool hasHwcLayer(int32_t displayId) { return getBE().mHwcLayers.count(displayId) > 0; } - HWC2::Layer* getHwcLayer(int32_t hwcId) { - if (getBE().mHwcLayers.count(hwcId) == 0) { + HWC2::Layer* getHwcLayer(int32_t displayId) { + if (getBE().mHwcLayers.count(displayId) == 0) { return nullptr; } - return getBE().mHwcLayers[hwcId].layer; + return getBE().mHwcLayers[displayId].layer; } // ----------------------------------------------------------------------- @@ -473,7 +471,7 @@ public: /* always call base class first */ static void miniDumpHeader(String8& result); - void miniDump(String8& result, int32_t hwcId) const; + void miniDump(String8& result, int32_t displayId) const; void dumpFrameStats(String8& result) const; void dumpFrameEvents(String8& result); void clearFrameStats(); diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 76b9543c35..f610677dc0 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -40,7 +40,6 @@ struct CompositionInfo { LayerBE* layer = nullptr; struct { HWC2::Layer* hwcLayer; - int32_t hwid = -1; sp fence; HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid; Rect displayFrame; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 995a96e11a..16c143f513 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1502,7 +1502,7 @@ void SurfaceFlinger::handleMessageRefresh() { mHadClientComposition = false; for (const auto& [token, display] : mDisplays) { mHadClientComposition = mHadClientComposition || - getBE().mHwc->hasClientComposition(display->getHwcDisplayId()); + getBE().mHwc->hasClientComposition(display->getId()); } mVsyncModulator.setLastFrameUsedRenderEngine(mHadClientComposition); @@ -1547,7 +1547,7 @@ void SurfaceFlinger::doDebugFlashRegions() status_t result = display->prepareFrame(*getBE().mHwc); ALOGE_IF(result != NO_ERROR, "prepareFrame for display %d failed: %d (%s)", - display->getHwcDisplayId(), result, strerror(-result)); + display->getId(), result, strerror(-result)); } } @@ -1789,13 +1789,13 @@ void SurfaceFlinger::rebuildLayerStacks() { } else { // Clear out the HWC layer if this layer was // previously visible, but no longer is - hwcLayerDestroyed = layer->destroyHwcLayer(display->getHwcDisplayId()); + hwcLayerDestroyed = layer->destroyHwcLayer(display->getId()); } } else { // WM changes display->layerStack upon sleep/awake. // Here we make sure we delete the HWC layers even if // WM changed their layer stack. - hwcLayerDestroyed = layer->destroyHwcLayer(display->getHwcDisplayId()); + hwcLayerDestroyed = layer->destroyHwcLayer(display->getId()); } // If a layer is not going to get a release fence because @@ -1917,8 +1917,8 @@ void SurfaceFlinger::setUpHWComposer() { bool mustRecompose = dirty && !(empty && wasEmpty); ALOGV_IF(display->isVirtual(), "Display %d: %s composition (%sdirty %sempty %swasEmpty)", - display->getHwcDisplayId(), mustRecompose ? "doing" : "skipping", - dirty ? "+" : "-", empty ? "+" : "-", wasEmpty ? "+" : "-"); + display->getId(), mustRecompose ? "doing" : "skipping", dirty ? "+" : "-", + empty ? "+" : "-", wasEmpty ? "+" : "-"); display->beginFrame(mustRecompose); @@ -1931,21 +1931,21 @@ void SurfaceFlinger::setUpHWComposer() { if (CC_UNLIKELY(mGeometryInvalid)) { mGeometryInvalid = false; for (const auto& [token, display] : mDisplays) { - const auto hwcId = display->getHwcDisplayId(); - if (hwcId >= 0) { + const auto displayId = display->getId(); + if (displayId >= 0) { const Vector>& currentLayers = display->getVisibleLayersSortedByZ(); for (size_t i = 0; i < currentLayers.size(); i++) { const auto& layer = currentLayers[i]; - if (!layer->hasHwcLayer(hwcId)) { - if (!layer->createHwcLayer(getBE().mHwc.get(), hwcId)) { - layer->forceClientComposition(hwcId); + if (!layer->hasHwcLayer(displayId)) { + if (!layer->createHwcLayer(getBE().mHwc.get(), displayId)) { + layer->forceClientComposition(displayId); continue; } } layer->setGeometry(display, i); if (mDebugDisableHWC || mDebugRegion) { - layer->forceClientComposition(hwcId); + layer->forceClientComposition(displayId); } } } @@ -1954,32 +1954,32 @@ void SurfaceFlinger::setUpHWComposer() { // Set the per-frame data for (const auto& [token, display] : mDisplays) { - const auto hwcId = display->getHwcDisplayId(); - - if (hwcId < 0) { + const auto displayId = display->getId(); + if (displayId < 0) { continue; } + if (mDrawingState.colorMatrixChanged) { display->setColorTransform(mDrawingState.colorMatrix); - status_t result = getBE().mHwc->setColorTransform(hwcId, mDrawingState.colorMatrix); + status_t result = getBE().mHwc->setColorTransform(displayId, mDrawingState.colorMatrix); ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display %d: %d", - display->getHwcDisplayId(), result); + displayId, result); } for (auto& layer : display->getVisibleLayersSortedByZ()) { if ((layer->getDataSpace() == Dataspace::BT2020_PQ || layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) && !display->hasHDR10Support()) { - layer->forceClientComposition(hwcId); + layer->forceClientComposition(displayId); } if ((layer->getDataSpace() == Dataspace::BT2020_HLG || layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) && !display->hasHLGSupport()) { - layer->forceClientComposition(hwcId); + layer->forceClientComposition(displayId); } - if (layer->getForceClientComposition(hwcId)) { + if (layer->getForceClientComposition(displayId)) { ALOGV("[%s] Requesting Client composition", layer->getName().string()); - layer->setCompositionType(hwcId, HWC2::Composition::Client); + layer->setCompositionType(displayId, HWC2::Composition::Client); continue; } @@ -2004,7 +2004,7 @@ void SurfaceFlinger::setUpHWComposer() { status_t result = display->prepareFrame(*getBE().mHwc); ALOGE_IF(result != NO_ERROR, "prepareFrame for display %d failed: %d (%s)", - display->getHwcDisplayId(), result, strerror(-result)); + display->getId(), result, strerror(-result)); } } @@ -2040,9 +2040,9 @@ void SurfaceFlinger::postFramebuffer() if (!display->isPoweredOn()) { continue; } - const auto hwcId = display->getHwcDisplayId(); - if (hwcId >= 0) { - getBE().mHwc->presentAndGetReleaseFences(hwcId); + const auto displayId = display->getId(); + if (displayId >= 0) { + getBE().mHwc->presentAndGetReleaseFences(displayId); } display->onSwapBuffersCompleted(); display->makeCurrent(); @@ -2050,15 +2050,15 @@ void SurfaceFlinger::postFramebuffer() // The layer buffer from the previous frame (if any) is released // by HWC only when the release fence from this frame (if any) is // signaled. Always get the release fence from HWC first. - auto hwcLayer = layer->getHwcLayer(hwcId); - sp releaseFence = getBE().mHwc->getLayerReleaseFence(hwcId, hwcLayer); + auto hwcLayer = layer->getHwcLayer(displayId); + sp releaseFence = getBE().mHwc->getLayerReleaseFence(displayId, hwcLayer); // If the layer was client composited in the previous frame, we // need to merge with the previous client target acquire fence. // Since we do not track that, always merge with the current // client target acquire fence when it is available, even though // this is suboptimal. - if (layer->getCompositionType(hwcId) == HWC2::Composition::Client) { + if (layer->getCompositionType(displayId) == HWC2::Composition::Client) { releaseFence = Fence::merge("LayerRelease", releaseFence, display->getClientTargetAcquireFence()); } @@ -2070,14 +2070,14 @@ void SurfaceFlinger::postFramebuffer() // display->getVisibleLayersSortedByZ. The best we can do is to // supply them with the present fence. if (!display->getLayersNeedingFences().isEmpty()) { - sp presentFence = getBE().mHwc->getPresentFence(hwcId); + sp presentFence = getBE().mHwc->getPresentFence(displayId); for (auto& layer : display->getLayersNeedingFences()) { layer->getBE().onLayerDisplayed(presentFence); } } - if (hwcId >= 0) { - getBE().mHwc->clearReleaseFences(hwcId); + if (displayId >= 0) { + getBE().mHwc->clearReleaseFences(displayId); } } @@ -2123,7 +2123,7 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) // here the transaction has been committed } -DisplayDevice::DisplayType SurfaceFlinger::determineDisplayType(hwc2_display_t display, +DisplayDevice::DisplayType SurfaceFlinger::determineDisplayType(hwc2_display_t hwcDisplayId, HWC2::Connection connection) const { // Figure out whether the event is for the primary display or an // external display by matching the Hwc display id against one for a @@ -2132,17 +2132,16 @@ DisplayDevice::DisplayType SurfaceFlinger::determineDisplayType(hwc2_display_t d // have a connected primary display, we assume the new display is meant to // be the primary display, and then if we don't have an external display, // we assume it is that. - const auto primaryDisplayId = - getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_PRIMARY); - const auto externalDisplayId = + const auto primaryHwcDisplayId = getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_PRIMARY); + const auto externalHwcDisplayId = getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_EXTERNAL); - if (primaryDisplayId && primaryDisplayId == display) { + if (primaryHwcDisplayId && primaryHwcDisplayId == hwcDisplayId) { return DisplayDevice::DISPLAY_PRIMARY; - } else if (externalDisplayId && externalDisplayId == display) { + } else if (externalHwcDisplayId && externalHwcDisplayId == hwcDisplayId) { return DisplayDevice::DISPLAY_EXTERNAL; - } else if (connection == HWC2::Connection::Connected && !primaryDisplayId) { + } else if (connection == HWC2::Connection::Connected && !primaryHwcDisplayId) { return DisplayDevice::DISPLAY_PRIMARY; - } else if (connection == HWC2::Connection::Connected && !externalDisplayId) { + } else if (connection == HWC2::Connection::Connected && !externalHwcDisplayId) { return DisplayDevice::DISPLAY_EXTERNAL; } @@ -2199,13 +2198,13 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { } sp SurfaceFlinger::setupNewDisplayDeviceInternal( - const wp& displayToken, int hwcId, const DisplayDeviceState& state, + const wp& displayToken, int32_t displayId, const DisplayDeviceState& state, const sp& dispSurface, const sp& producer) { bool hasWideColorGamut = false; std::unordered_map> hwcColorModes; if (hasWideColorDisplay) { - std::vector modes = getHwComposer().getColorModes(hwcId); + std::vector modes = getHwComposer().getColorModes(displayId); for (ColorMode colorMode : modes) { switch (colorMode) { case ColorMode::DISPLAY_P3: @@ -2217,14 +2216,14 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( break; } - std::vector renderIntents = getHwComposer().getRenderIntents(hwcId, - colorMode); + std::vector renderIntents = + getHwComposer().getRenderIntents(displayId, colorMode); hwcColorModes.emplace(colorMode, renderIntents); } } HdrCapabilities hdrCapabilities; - getHwComposer().getHdrCapabilities(hwcId, &hdrCapabilities); + getHwComposer().getHdrCapabilities(displayId, &hdrCapabilities); auto nativeWindowSurface = mCreateNativeWindowSurface(producer); auto nativeWindow = nativeWindowSurface->getNativeWindow(); @@ -2254,11 +2253,11 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( auto initialPowerMode = state.isVirtual() ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF; sp display = - new DisplayDevice(this, state.type, hwcId, state.isSecure, displayToken, nativeWindow, - dispSurface, std::move(renderSurface), displayWidth, displayHeight, - hasWideColorGamut, hdrCapabilities, - getHwComposer().getSupportedPerFrameMetadata(hwcId), hwcColorModes, - initialPowerMode); + new DisplayDevice(this, state.type, displayId, state.isSecure, displayToken, + nativeWindow, dispSurface, std::move(renderSurface), displayWidth, + displayHeight, hasWideColorGamut, hdrCapabilities, + getHwComposer().getSupportedPerFrameMetadata(displayId), + hwcColorModes, initialPowerMode); if (maxFrameBufferAcquiredBuffers >= 3) { nativeWindowSurface->preallocateBuffers(); @@ -2362,7 +2361,7 @@ void SurfaceFlinger::processDisplayChangesLocked() { sp bqConsumer; mCreateBufferQueue(&bqProducer, &bqConsumer, false); - int32_t hwcId = -1; + int32_t displayId = -1; if (state.isVirtual()) { // Virtual displays without a surface are dormant: // they have external state (layer stack, projection, @@ -2381,13 +2380,14 @@ void SurfaceFlinger::processDisplayChangesLocked() { ALOGE_IF(status != NO_ERROR, "Unable to query format (%d)", status); auto format = static_cast(intFormat); - getBE().mHwc->allocateVirtualDisplay(width, height, &format, &hwcId); + getBE().mHwc->allocateVirtualDisplay(width, height, &format, + &displayId); } // TODO: Plumb requested format back up to consumer sp vds = - new VirtualDisplaySurface(*getBE().mHwc, hwcId, state.surface, + new VirtualDisplaySurface(*getBE().mHwc, displayId, state.surface, bqProducer, bqConsumer, state.displayName); @@ -2400,15 +2400,15 @@ void SurfaceFlinger::processDisplayChangesLocked() { "surface is provided (%p), ignoring it", state.surface.get()); - hwcId = state.type; - dispSurface = new FramebufferSurface(*getBE().mHwc, hwcId, bqConsumer); + displayId = state.type; + dispSurface = new FramebufferSurface(*getBE().mHwc, displayId, bqConsumer); producer = bqProducer; } const wp& displayToken = curr.keyAt(i); if (dispSurface != nullptr) { mDisplays.emplace(displayToken, - setupNewDisplayDeviceInternal(displayToken, hwcId, state, + setupNewDisplayDeviceInternal(displayToken, displayId, state, dispSurface, producer)); if (!state.isVirtual()) { mEventThread->onHotplugReceived(state.type, true); @@ -2556,7 +2556,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) void SurfaceFlinger::updateCursorAsync() { for (const auto& [token, display] : mDisplays) { - if (display->getHwcDisplayId() < 0) { + if (display->getId() < 0) { continue; } @@ -2804,7 +2804,7 @@ void SurfaceFlinger::doDisplayComposition(const sp& display // 1) It is being handled by hardware composer, which may need this to // keep its virtual display state machine in sync, or // 2) There is work to be done (the dirty region isn't empty) - bool isHwcDisplay = display->getHwcDisplayId() >= 0; + bool isHwcDisplay = display->getId() >= 0; if (!isHwcDisplay && inDirtyRegion.isEmpty()) { ALOGV("Skipping display composition"); return; @@ -2822,8 +2822,8 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& display) { const Region bounds(display->bounds()); const DisplayRenderArea renderArea(display); - const auto hwcId = display->getHwcDisplayId(); - const bool hasClientComposition = getBE().mHwc->hasClientComposition(hwcId); + const auto displayId = display->getId(); + const bool hasClientComposition = getBE().mHwc->hasClientComposition(displayId); ATRACE_INT("hasClientComposition", hasClientComposition); bool applyColorMatrix = false; @@ -2841,7 +2841,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& display) { getBE().mRenderEngine->setDisplayMaxLuminance( display->getHdrCapabilities().getDesiredMaxLuminance()); - const bool hasDeviceComposition = getBE().mHwc->hasDeviceComposition(hwcId); + const bool hasDeviceComposition = getBE().mHwc->hasDeviceComposition(displayId); const bool skipClientColorTransform = getBE().mHwc->hasCapability( HWC2::Capability::SkipClientColorTransform); @@ -2920,18 +2920,16 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& display) { const Region clip(bounds.intersect( displayTransform.transform(layer->visibleRegion))); ALOGV("Layer: %s", layer->getName().string()); - ALOGV(" Composition type: %s", - to_string(layer->getCompositionType(hwcId)).c_str()); + ALOGV(" Composition type: %s", to_string(layer->getCompositionType(displayId)).c_str()); if (!clip.isEmpty()) { - switch (layer->getCompositionType(hwcId)) { + switch (layer->getCompositionType(displayId)) { case HWC2::Composition::Cursor: case HWC2::Composition::Device: case HWC2::Composition::Sideband: case HWC2::Composition::SolidColor: { const Layer::State& state(layer->getDrawingState()); - if (layer->getClearClientTarget(hwcId) && !firstLayer && - layer->isOpaque(state) && (state.color.a == 1.0f) - && hasClientComposition) { + if (layer->getClearClientTarget(displayId) && !firstLayer && + layer->isOpaque(state) && (state.color.a == 1.0f) && hasClientComposition) { // never clear the very first layer since we're // guaranteed the FB is already cleared layer->clearWithOpenGL(renderArea); @@ -3623,7 +3621,7 @@ void SurfaceFlinger::initializeDisplays() { void SurfaceFlinger::setPowerModeInternal(const sp& display, int mode, bool stateLockHeld) { - const int32_t displayId = display->getHwcDisplayId(); + const int32_t displayId = display->getId(); ALOGD("Setting power mode %d on display %d", mode, displayId); int currentMode = display->getPowerMode(); @@ -4018,16 +4016,16 @@ void SurfaceFlinger::dumpBufferingStats(String8& result) const { void SurfaceFlinger::dumpDisplayIdentificationData(String8& result) const { for (const auto& [token, display] : mDisplays) { - const int32_t hwcId = display->getHwcDisplayId(); - const auto displayId = getHwComposer().getHwcDisplayId(hwcId); - if (!displayId) { + const int32_t displayId = display->getId(); + const auto hwcDisplayId = getHwComposer().getHwcDisplayId(displayId); + if (!hwcDisplayId) { continue; } - result.appendFormat("Display %d: ", hwcId); + result.appendFormat("Display %d (HWC display %" PRIu64 "): ", displayId, *hwcDisplayId); uint8_t port; DisplayIdentificationData data; - if (!getHwComposer().getDisplayIdentificationData(*displayId, &port, &data)) { + if (!getHwComposer().getDisplayIdentificationData(*hwcDisplayId, &port, &data)) { result.append("no identification data\n"); continue; } @@ -4066,13 +4064,13 @@ void SurfaceFlinger::dumpWideColorInfo(String8& result) const { // TODO: print out if wide-color mode is active or not for (const auto& [token, display] : mDisplays) { - const int32_t hwcId = display->getHwcDisplayId(); - if (hwcId == DisplayDevice::DISPLAY_ID_INVALID) { + const int32_t displayId = display->getId(); + if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { continue; } - result.appendFormat("Display %d color modes:\n", hwcId); - std::vector modes = getHwComposer().getColorModes(hwcId); + result.appendFormat("Display %d color modes:\n", displayId); + std::vector modes = getHwComposer().getColorModes(displayId); for (auto&& mode : modes) { result.appendFormat(" %s (%d)\n", decodeColorMode(mode).c_str(), mode); } @@ -4107,11 +4105,11 @@ LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(const DisplayDevice& disp layersProto.set_color_transform(decodeColorTransform(display.getColorTransform())); layersProto.set_global_transform(static_cast(display.getOrientationTransform())); - const int32_t hwcId = display.getHwcDisplayId(); + const int32_t displayId = display.getId(); mDrawingState.traverseInZOrder([&](Layer* layer) { - if (!layer->visibleRegion.isEmpty() && layer->getBE().mHwcLayers.count(hwcId)) { + if (!layer->visibleRegion.isEmpty() && layer->getBE().mHwcLayers.count(displayId)) { LayerProto* layerProto = layersProto.add_layers(); - layer->writeToProto(layerProto, hwcId); + layer->writeToProto(layerProto, displayId); } }); @@ -4258,16 +4256,14 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, * HWC layer minidump */ for (const auto& [token, display] : mDisplays) { - const int32_t hwcId = display->getHwcDisplayId(); - if (hwcId == DisplayDevice::DISPLAY_ID_INVALID) { + const int32_t displayId = display->getId(); + if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { continue; } - result.appendFormat("Display %d HWC layers:\n", hwcId); + result.appendFormat("Display %d HWC layers:\n", displayId); Layer::miniDumpHeader(result); - mCurrentState.traverseInZOrder([&](Layer* layer) { - layer->miniDump(result, hwcId); - }); + mCurrentState.traverseInZOrder([&](Layer* layer) { layer->miniDump(result, displayId); }); result.append("\n"); } @@ -4298,18 +4294,17 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, } } -const Vector< sp >& -SurfaceFlinger::getLayerSortedByZForHwcDisplay(int id) { +const Vector>& SurfaceFlinger::getLayerSortedByZForHwcDisplay(int32_t displayId) { // Note: mStateLock is held here wp displayToken; for (const auto& [token, display] : mDisplays) { - if (display->getHwcDisplayId() == id) { + if (display->getId() == displayId) { displayToken = token; break; } } if (displayToken == nullptr) { - ALOGE("getLayerSortedByZForHwcDisplay: invalid hwc display id %d", id); + ALOGE("getLayerSortedByZForHwcDisplay: Invalid display %d", displayId); // Just use the primary display so we have something to return displayToken = getBuiltInDisplay(DisplayDevice::DISPLAY_PRIMARY); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index a4e20b8a8f..3954fa7dfa 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -677,7 +677,8 @@ private: */ DisplayDevice::DisplayType determineDisplayType(hwc2_display_t display, HWC2::Connection connection) const; - sp setupNewDisplayDeviceInternal(const wp& displayToken, int hwcId, + sp setupNewDisplayDeviceInternal(const wp& displayToken, + int32_t displayId, const DisplayDeviceState& state, const sp& dispSurface, const sp& producer); diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index 0b6a9b1d1e..1a7805aaf6 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -234,8 +234,8 @@ const DisplayDeviceState& DisplayTransactionTest::getDrawingDisplayState(sp +template struct DisplayVariant { // The display width and height static constexpr int WIDTH = width; @@ -245,7 +245,7 @@ struct DisplayVariant { // The type for this display static constexpr DisplayDevice::DisplayType TYPE = type; - static constexpr DisplayDevice::DisplayType HWCOMPOSER_ID = hwcId; + static constexpr DisplayDevice::DisplayType DISPLAY_ID = displayId; // When creating native window surfaces for the framebuffer, whether those should be critical static constexpr Critical CRITICAL = critical; @@ -257,7 +257,7 @@ struct DisplayVariant { static constexpr Secure SECURE = secure; static auto makeFakeExistingDisplayInjector(DisplayTransactionTest* test) { - auto injector = FakeDisplayDeviceInjector(test->mFlinger, TYPE, HWCOMPOSER_ID); + auto injector = FakeDisplayDeviceInjector(test->mFlinger, TYPE, DISPLAY_ID); injector.setSecure(static_cast(SECURE)); return injector; } diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index f512fba938..5dcac92d5d 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -70,11 +70,11 @@ public: auto resetDisplayState() { return mFlinger->resetDisplayState(); } - auto setupNewDisplayDeviceInternal(const wp& displayToken, int hwcId, + auto setupNewDisplayDeviceInternal(const wp& displayToken, int32_t displayId, const DisplayDeviceState& state, const sp& dispSurface, const sp& producer) { - return mFlinger->setupNewDisplayDeviceInternal(displayToken, hwcId, state, dispSurface, + return mFlinger->setupNewDisplayDeviceInternal(displayToken, displayId, state, dispSurface, producer); } @@ -255,8 +255,8 @@ public: class FakeDisplayDeviceInjector { public: FakeDisplayDeviceInjector(TestableSurfaceFlinger& flinger, DisplayDevice::DisplayType type, - int hwcId) - : mFlinger(flinger), mType(type), mHwcId(hwcId) {} + int32_t displayId) + : mFlinger(flinger), mType(type), mDisplayId(displayId) {} sp token() const { return mDisplayToken; } @@ -301,10 +301,10 @@ public: sp inject() { std::unordered_map> hdrAndRenderIntents; sp device = - new DisplayDevice(mFlinger.mFlinger.get(), mType, mHwcId, mSecure, mDisplayToken, - mNativeWindow, mDisplaySurface, std::move(mRenderSurface), 0, - 0, false, HdrCapabilities(), 0, hdrAndRenderIntents, - HWC_POWER_MODE_NORMAL); + new DisplayDevice(mFlinger.mFlinger.get(), mType, mDisplayId, mSecure, + mDisplayToken, mNativeWindow, mDisplaySurface, + std::move(mRenderSurface), 0, 0, false, HdrCapabilities(), 0, + hdrAndRenderIntents, HWC_POWER_MODE_NORMAL); mFlinger.mutableDisplays().emplace(mDisplayToken, device); DisplayDeviceState state; @@ -324,7 +324,7 @@ public: TestableSurfaceFlinger& mFlinger; sp mDisplayToken = new BBinder(); DisplayDevice::DisplayType mType; - int mHwcId; + const int32_t mDisplayId; sp mNativeWindow; sp mDisplaySurface; std::unique_ptr mRenderSurface; -- cgit v1.2.3-59-g8ed1b From fd46261518bac66441a57c3732811f5340b69978 Mon Sep 17 00:00:00 2001 From: chaviw Date: Thu, 31 May 2018 16:11:27 -0700 Subject: Use correct StateSet for LayerVector compare. Currently LayerVector compare function was using the current StateSet. This is incorect since the LayerVector may be created with the intention of sorting the layers by drawing state. Instead, create the LayerVector with a specified StateSet so the compare function always uses the correct state. This fixes an issue where the layers were getting added and sorted by current state z order but the caller expected the order to be by drawing state z order. Change-Id: I7afef556fa72f687bcfeb0a642465488cc72f40b Fixes: 80516823 Test: No longer flicker when IME closes. Logs show correct z order. --- services/surfaceflinger/Layer.cpp | 7 ++++--- services/surfaceflinger/LayerVector.cpp | 25 ++++++++++++++++++------- services/surfaceflinger/LayerVector.h | 13 +++++++++---- services/surfaceflinger/SurfaceFlinger.h | 2 +- 4 files changed, 32 insertions(+), 15 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 8c1199b8a1..10b3443ac4 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -94,6 +94,8 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n mLastFrameNumberReceived(0), mAutoRefresh(false), mFreezeGeometryUpdates(false), + mCurrentChildren(LayerVector::StateSet::Current), + mDrawingChildren(LayerVector::StateSet::Drawing), mBE{this, name.string()} { mCurrentCrop.makeInvalid(); @@ -133,7 +135,6 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n CompositorTiming compositorTiming; flinger->getCompositorTiming(&compositorTiming); mFrameEventHistory.initializeCompositorTiming(compositorTiming); - } void Layer::onFirstRef() {} @@ -1677,7 +1678,7 @@ __attribute__((no_sanitize("unsigned-integer-overflow"))) LayerVector Layer::mak return children; } - LayerVector traverse; + LayerVector traverse(stateSet); for (const wp& weakRelative : state.zOrderRelatives) { sp strongRelative = weakRelative.promote(); if (strongRelative != nullptr) { @@ -1775,7 +1776,7 @@ LayerVector Layer::makeChildrenTraversalList(LayerVector::StateSet stateSet, const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; const State& state = useDrawing ? mDrawingState : mCurrentState; - LayerVector traverse; + LayerVector traverse(stateSet); for (const wp& weakRelative : state.zOrderRelatives) { sp strongRelative = weakRelative.promote(); // Only add relative layers that are also descendents of the top most parent of the tree. diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp index 47156c19d2..84945247a6 100644 --- a/services/surfaceflinger/LayerVector.cpp +++ b/services/surfaceflinger/LayerVector.cpp @@ -19,26 +19,37 @@ namespace android { -LayerVector::LayerVector() = default; +LayerVector::LayerVector(const StateSet stateSet) : mStateSet(stateSet) {} -LayerVector::LayerVector(const LayerVector& rhs) : SortedVector>(rhs) { -} +LayerVector::LayerVector(const LayerVector& rhs, const StateSet stateSet) + : SortedVector>(rhs), mStateSet(stateSet) {} LayerVector::~LayerVector() = default; +// This operator override is needed to prevent mStateSet from getting copied over. +LayerVector& LayerVector::operator=(const LayerVector& rhs) { + SortedVector::operator=(rhs); + return *this; +} + int LayerVector::do_compare(const void* lhs, const void* rhs) const { // sort layers per layer-stack, then by z-order and finally by sequence const auto& l = *reinterpret_cast*>(lhs); const auto& r = *reinterpret_cast*>(rhs); - uint32_t ls = l->getCurrentState().layerStack; - uint32_t rs = r->getCurrentState().layerStack; + const auto& lState = + (mStateSet == StateSet::Current) ? l->getCurrentState() : l->getDrawingState(); + const auto& rState = + (mStateSet == StateSet::Current) ? r->getCurrentState() : r->getDrawingState(); + + uint32_t ls = lState.layerStack; + uint32_t rs = rState.layerStack; if (ls != rs) return (ls > rs) ? 1 : -1; - int32_t lz = l->getCurrentState().z; - int32_t rz = r->getCurrentState().z; + int32_t lz = lState.z; + int32_t rz = rState.z; if (lz != rz) return (lz > rz) ? 1 : -1; diff --git a/services/surfaceflinger/LayerVector.h b/services/surfaceflinger/LayerVector.h index a9adb4113a..88d7711bb8 100644 --- a/services/surfaceflinger/LayerVector.h +++ b/services/surfaceflinger/LayerVector.h @@ -32,22 +32,27 @@ class Layer; */ class LayerVector : public SortedVector> { public: - LayerVector(); - LayerVector(const LayerVector& rhs); - ~LayerVector() override; - enum class StateSet { Invalid, Current, Drawing, }; + explicit LayerVector(const StateSet stateSet); + LayerVector(const LayerVector& rhs, const StateSet stateSet); + ~LayerVector() override; + + LayerVector& operator=(const LayerVector& rhs); + // Sorts layer by layer-stack, Z order, and finally creation order (sequence). int do_compare(const void* lhs, const void* rhs) const override; using Visitor = std::function; void traverseInReverseZOrder(StateSet stateSet, const Visitor& visitor) const; void traverseInZOrder(StateSet stateSet, const Visitor& visitor) const; + +private: + const StateSet mStateSet; }; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 750f2ec39d..e58287a6b9 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -371,7 +371,7 @@ private: class State { public: - explicit State(LayerVector::StateSet set) : stateSet(set) {} + explicit State(LayerVector::StateSet set) : stateSet(set), layersSortedByZ(set) {} State& operator=(const State& other) { // We explicitly don't copy stateSet so that, e.g., mDrawingState // always uses the Drawing StateSet. -- cgit v1.2.3-59-g8ed1b From 6ca3519c86bc27562a75e071163364f43257fb5b Mon Sep 17 00:00:00 2001 From: Yichi Chen Date: Tue, 29 May 2018 12:20:43 +0800 Subject: Surfaceflinger: Add transform info into dumpsys The minor dumpsys SurfaceFlinger enhancement explicitly exposes the transform info of active buffers and HWC layers. It helps developers understand more about when and why HWC layers are rotated. Bug: b/80267683 Test: Keep dumpsys SurfaceFlinger during monkey test Change-Id: Ia0d78170129346891cb6834736f7eff7d13c32d3 --- services/surfaceflinger/Layer.cpp | 19 +++++++++++++------ .../surfaceflinger/layerproto/LayerProtoParser.cpp | 2 ++ .../layerproto/include/layerproto/LayerProtoParser.h | 1 + services/surfaceflinger/layerproto/layers.proto | 2 ++ 4 files changed, 18 insertions(+), 6 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f148759c67..e17589f93a 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1438,15 +1438,18 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { } void Layer::miniDumpHeader(String8& result) { - result.append("----------------------------------------"); - result.append("---------------------------------------\n"); + result.append("-------------------------------"); + result.append("-------------------------------"); + result.append("-----------------------------\n"); result.append(" Layer name\n"); result.append(" Z | "); result.append(" Comp Type | "); + result.append(" Transform | "); result.append(" Disp Frame (LTRB) | "); result.append(" Source Crop (LTRB)\n"); - result.append("----------------------------------------"); - result.append("---------------------------------------\n"); + result.append("-------------------------------"); + result.append("-------------------------------"); + result.append("-----------------------------\n"); } void Layer::miniDump(String8& result, int32_t displayId) const { @@ -1475,13 +1478,15 @@ void Layer::miniDump(String8& result, int32_t displayId) const { result.appendFormat(" %10d | ", layerState.z); } result.appendFormat("%10s | ", to_string(getCompositionType(displayId)).c_str()); + result.appendFormat("%10s | ", to_string(hwcInfo.transform).c_str()); const Rect& frame = hwcInfo.displayFrame; 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.append("- - - - - - - - - - - - - - - - - - - - "); - result.append("- - - - - - - - - - - - - - - - - - - -\n"); + result.append("- - - - - - - - - - - - - - - -"); + result.append("- - - - - - - - - - - - - - - -"); + result.append("- - - - - - - - - - - - - - -\n"); } void Layer::dumpFrameStats(String8& result) const { @@ -1964,6 +1969,8 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) auto buffer = getBE().compositionInfo.mBuffer; if (buffer != nullptr) { LayerProtoHelper::writeToProto(buffer, layerInfo->mutable_active_buffer()); + LayerProtoHelper::writeToProto(Transform(mCurrentTransform), + layerInfo->mutable_buffer_transform()); } layerInfo->set_queued_frames(getQueuedFrameCount()); diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index fcf42f00a9..e1c0fd340d 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -114,6 +114,7 @@ LayerProtoParser::Layer* LayerProtoParser::generateLayer(const LayerProto& layer layer->transform = generateTransform(layerProto.transform()); layer->requestedTransform = generateTransform(layerProto.requested_transform()); layer->activeBuffer = generateActiveBuffer(layerProto.active_buffer()); + layer->bufferTransform = generateTransform(layerProto.buffer_transform()); layer->queuedFrames = layerProto.queued_frames(); layer->refreshPending = layerProto.refresh_pending(); layer->hwcFrame = generateRect(layerProto.hwc_frame()); @@ -312,6 +313,7 @@ std::string LayerProtoParser::Layer::to_string() const { StringAppendF(&result, " zOrderRelativeOf=%s\n", zOrderRelativeOf == nullptr ? "none" : zOrderRelativeOf->name.c_str()); StringAppendF(&result, " activeBuffer=%s,", activeBuffer.to_string().c_str()); + StringAppendF(&result, " tr=%s", bufferTransform.to_string().c_str()); StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d,", queuedFrames, refreshPending); StringAppendF(&result, " windowType=%d, appId=%d", windowType, appId); diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index 74a6f28f2b..360e5997d1 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -105,6 +105,7 @@ public: Layer* parent = 0; Layer* zOrderRelativeOf = 0; LayerProtoParser::ActiveBuffer activeBuffer; + Transform bufferTransform; int32_t queuedFrames; bool refreshPending; LayerProtoParser::Rect hwcFrame; diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index 77c6675b7f..eb346944af 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -80,6 +80,8 @@ message LayerProto { optional int32 hwc_composition_type = 35; // If it's a buffer layer, indicate if the content is protected optional bool is_protected = 36; + // If active_buffer is not null, record its transform + optional TransformProto buffer_transform = 37; } message PositionProto { -- cgit v1.2.3-59-g8ed1b From 91b1df2ff45e4ab1db0c7fe80287d0b2faa09e77 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Mon, 18 Jun 2018 18:00:16 -0700 Subject: [SurfaceFlinger] Checking nullptr for HWC layer. There were several places where we didn't check nullptr when accessing HWC layer, which results in function call on nullptr when external display was disconnected. This patch makes sure we check HWC layer before calling functions on it. BUG: 80325674 Test: Build, flash, boot, watch videos Change-Id: I302ad4eeea5c196daadcdccb596dac60b02d3845 --- services/surfaceflinger/BufferLayer.cpp | 8 ++++++-- services/surfaceflinger/ColorLayer.cpp | 5 +++++ services/surfaceflinger/Layer.cpp | 9 +++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 133e8f7aa1..df6404ad4d 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -613,6 +613,11 @@ void BufferLayer::setPerFrameData(const sp& display) { const auto& viewport = display->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); const auto displayId = display->getId(); + if (!hasHwcLayer(displayId)) { + ALOGE("[%s] failed to setPerFrameData: no HWC layer found (%d)", + mName.string(), displayId); + return; + } auto& hwcInfo = getBE().mHwcLayers[displayId]; auto& hwcLayer = hwcInfo.layer; auto error = hwcLayer->setVisibleRegion(visible); @@ -667,8 +672,7 @@ void BufferLayer::setPerFrameData(const sp& display) { uint32_t hwcSlot = 0; sp hwcBuffer; - getBE().mHwcLayers[displayId].bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, - &hwcSlot, &hwcBuffer); + hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, &hwcSlot, &hwcBuffer); auto acquireFence = mConsumer->getCurrentFence(); error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence); diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index ab8afb644b..aebe4eae9a 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -66,6 +66,11 @@ void ColorLayer::setPerFrameData(const sp& display) { const auto& viewport = display->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); const auto displayId = display->getId(); + if (!hasHwcLayer(displayId)) { + ALOGE("[%s] failed to setPerFrameData: no HWC layer found (%d)", + mName.string(), displayId); + return; + } auto& hwcInfo = getBE().mHwcLayers[displayId]; auto& hwcLayer = hwcInfo.layer; auto error = hwcLayer->setVisibleRegion(visible); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e17589f93a..5a0bf43022 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -482,6 +482,11 @@ FloatRect Layer::computeCrop(const sp& hw) const { void Layer::setGeometry(const sp& display, uint32_t z) { const auto displayId = display->getId(); + if (!hasHwcLayer(displayId)) { + ALOGE("[%s] failed to setGeometry: no HWC layer found (%d)", + mName.string(), displayId); + return; + } auto& hwcInfo = getBE().mHwcLayers[displayId]; // enable this layer @@ -1980,6 +1985,10 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) } void Layer::writeToProto(LayerProto* layerInfo, int32_t displayId) { + if (!hasHwcLayer(displayId)) { + return; + } + writeToProto(layerInfo, LayerVector::StateSet::Drawing); const auto& hwcInfo = getBE().mHwcLayers.at(displayId); -- cgit v1.2.3-59-g8ed1b From a2edf615f9a185918654867e28c5d999f9d74900 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Fri, 1 Jun 2018 13:15:16 -0700 Subject: SF: Clean up remaining display identifiers Bug: 74619554 Test: Build Change-Id: Icd8457b6496f02c6010c724cfa6ae678f6e01adf --- services/surfaceflinger/BufferLayer.cpp | 3 +- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 43 ++++++++++------------ .../surfaceflinger/DisplayHardware/HWComposer.h | 7 ++-- services/surfaceflinger/Layer.cpp | 14 +++---- services/surfaceflinger/Layer.h | 8 ++-- services/surfaceflinger/SurfaceFlinger.cpp | 23 ++++++------ services/surfaceflinger/SurfaceFlinger.h | 15 ++++---- .../tests/unittests/DisplayTransactionTest.cpp | 14 +++---- .../tests/unittests/TestableSurfaceFlinger.h | 5 ++- 9 files changed, 63 insertions(+), 69 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 133e8f7aa1..36eb9e33b4 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -706,8 +706,7 @@ void BufferLayer::onFirstRef() { mProducer->setMaxDequeuedBufferCount(2); } - const sp hw(mFlinger->getDefaultDisplayDevice()); - updateTransformHint(hw); + updateTransformHint(mFlinger->getDefaultDisplayDevice()); } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 4617cb5da7..1118eeb719 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -96,17 +96,16 @@ void HWComposer::registerCallback(HWC2::ComposerCallback* callback, mHwcDevice->registerCallback(callback, sequenceId); } -bool HWComposer::getDisplayIdentificationData(hwc2_display_t displayId, uint8_t* outPort, +bool HWComposer::getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort, DisplayIdentificationData* outData) const { - HWC2::Display* display = mHwcDevice->getDisplayById(displayId); + HWC2::Display* display = mHwcDevice->getDisplayById(hwcDisplayId); if (!display) { - ALOGE("getDisplayIdentificationData: Attempted to access invalid display %" PRIu64, - displayId); + ALOGE("%s: Attempted to access invalid display %" PRIu64, __FUNCTION__, hwcDisplayId); return false; } const auto error = display->getIdentificationData(outPort, outData); if (error != HWC2::Error::None) { - ALOGE("getDisplayIdentificationData failed for display %" PRIu64, displayId); + ALOGE("%s failed for display %" PRIu64, __FUNCTION__, hwcDisplayId); return false; } return true; @@ -147,49 +146,47 @@ void HWComposer::validateChange(HWC2::Composition from, HWC2::Composition to) { } } -std::optional HWComposer::onHotplug(hwc2_display_t displayId, int32_t displayType, +std::optional HWComposer::onHotplug(hwc2_display_t hwcDisplayId, int32_t displayType, HWC2::Connection connection) { if (displayType >= HWC_NUM_PHYSICAL_DISPLAY_TYPES) { ALOGE("Invalid display type of %d", displayType); return {}; } - ALOGV("hotplug: %" PRIu64 ", %s %s", displayId, - displayType == DisplayDevice::DISPLAY_PRIMARY ? "primary" : "external", - to_string(connection).c_str()); - mHwcDevice->onHotplug(displayId, connection); + ALOGV("hotplug: %" PRIu64 ", %s %s", hwcDisplayId, + displayType == DisplayDevice::DISPLAY_PRIMARY ? "primary" : "external", + to_string(connection).c_str()); + mHwcDevice->onHotplug(hwcDisplayId, connection); - std::optional stableId; + std::optional displayId; uint8_t port; DisplayIdentificationData data; - if (getDisplayIdentificationData(displayId, &port, &data)) { - stableId = generateDisplayId(port, data); - ALOGE_IF(!stableId, "Failed to generate stable ID for display %" PRIu64, displayId); + if (getDisplayIdentificationData(hwcDisplayId, &port, &data)) { + displayId = generateDisplayId(port, data); + ALOGE_IF(!displayId, "Failed to generate stable ID for display %" PRIu64, hwcDisplayId); } // Disconnect is handled through HWComposer::disconnectDisplay via // SurfaceFlinger's onHotplugReceived callback handling if (connection == HWC2::Connection::Connected) { - mDisplayData[displayType].hwcDisplay = mHwcDevice->getDisplayById(displayId); - mHwcDisplaySlots[displayId] = displayType; + mDisplayData[displayType].hwcDisplay = mHwcDevice->getDisplayById(hwcDisplayId); + mHwcDisplaySlots[hwcDisplayId] = displayType; } - return stableId; + return displayId; } -bool HWComposer::onVsync(hwc2_display_t displayId, int64_t timestamp, - int32_t* outDisplay) { - auto display = mHwcDevice->getDisplayById(displayId); +bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp, int32_t* outDisplay) { + auto display = mHwcDevice->getDisplayById(hwcDisplayId); if (!display) { - ALOGE("onVsync Failed to find display %" PRIu64, displayId); + ALOGE("%s: Failed to find display %" PRIu64, __FUNCTION__, hwcDisplayId); return false; } auto displayType = HWC2::DisplayType::Invalid; auto error = display->getType(&displayType); if (error != HWC2::Error::None) { - ALOGE("onVsync: Failed to determine type of display %" PRIu64, - display->getId()); + ALOGE("%s: Failed to determine type of display %" PRIu64, __FUNCTION__, display->getId()); return false; } diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 4b6c367bab..b292a047d7 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -76,7 +76,7 @@ public: void registerCallback(HWC2::ComposerCallback* callback, int32_t sequenceId); - bool getDisplayIdentificationData(hwc2_display_t displayId, uint8_t* outPort, + bool getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort, DisplayIdentificationData* outData) const; bool hasCapability(HWC2::Capability capability) const; @@ -152,9 +152,8 @@ public: // Returns true if successful, false otherwise. The // DisplayDevice::DisplayType of the display is returned as an output param. - bool onVsync(hwc2_display_t displayId, int64_t timestamp, - int32_t* outDisplay); - std::optional onHotplug(hwc2_display_t displayId, int32_t displayType, + bool onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp, int32_t* outDisplay); + std::optional onHotplug(hwc2_display_t hwcDisplayId, int32_t displayType, HWC2::Connection connection); void setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e17589f93a..c8b6cda46e 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -363,7 +363,7 @@ FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const { return reduce(floatWin, activeTransparentRegion); } -Rect Layer::computeInitialCrop(const sp& hw) const { +Rect Layer::computeInitialCrop(const sp& display) const { // the crop is the area of the window that gets cropped, but not // scaled in any ways. const State& s(getDrawingState()); @@ -382,7 +382,7 @@ Rect Layer::computeInitialCrop(const sp& hw) const { Transform t = getTransform(); activeCrop = t.transform(activeCrop); - if (!activeCrop.intersect(hw->getViewport(), &activeCrop)) { + if (!activeCrop.intersect(display->getViewport(), &activeCrop)) { activeCrop.clear(); } if (!s.finalCrop.isEmpty()) { @@ -393,14 +393,14 @@ Rect Layer::computeInitialCrop(const sp& hw) const { const auto& p = mDrawingParent.promote(); if (p != nullptr) { - auto parentCrop = p->computeInitialCrop(hw); + auto parentCrop = p->computeInitialCrop(display); activeCrop.intersect(parentCrop, &activeCrop); } return activeCrop; } -FloatRect Layer::computeCrop(const sp& hw) const { +FloatRect Layer::computeCrop(const sp& display) const { // the content crop is the area of the content that gets scaled to the // layer's size. This is in buffer space. FloatRect crop = getContentCrop().toFloatRect(); @@ -409,7 +409,7 @@ FloatRect Layer::computeCrop(const sp& hw) const { const State& s(getDrawingState()); // Screen space to make reduction to parent crop clearer. - Rect activeCrop = computeInitialCrop(hw); + Rect activeCrop = computeInitialCrop(display); Transform t = getTransform(); // Back to layer space to work with the content crop. activeCrop = t.inverse().transform(activeCrop); @@ -1371,13 +1371,13 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const { return usage; } -void Layer::updateTransformHint(const sp& hw) const { +void Layer::updateTransformHint(const sp& display) const { uint32_t orientation = 0; if (!mFlinger->mDebugDisableTransformHint) { // The transform hint is used to improve performance, but we can // only have a single transform hint, it cannot // apply to all displays. - const Transform& planeTransform(hw->getTransform()); + const Transform& planeTransform = display->getTransform(); orientation = planeTransform.getOrientation(); if (orientation & Transform::ROT_INVALID) { orientation = 0; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index fe953cd2e2..fb94058d0d 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -328,7 +328,7 @@ public: HWC2::Composition getCompositionType(int32_t displayId) const; void setClearClientTarget(int32_t displayId, bool clear); bool getClearClientTarget(int32_t displayId) const; - void updateCursorPosition(const sp& hw); + void updateCursorPosition(const sp& display); /* * called after page-flip @@ -425,7 +425,7 @@ public: // Updates the transform hint in our SurfaceFlingerConsumer to match // the current orientation of the display device. - void updateTransformHint(const sp& hw) const; + void updateTransformHint(const sp& display) const; /* * returns the rectangle that crops the content of the layer and scales it @@ -556,12 +556,12 @@ protected: uint32_t getEffectiveUsage(uint32_t usage) const; - FloatRect computeCrop(const sp& hw) const; + FloatRect computeCrop(const sp& display) 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. - Rect computeInitialCrop(const sp& hw) const; + Rect computeInitialCrop(const sp& display) const; // drawing void clearWithOpenGL(const RenderArea& renderArea, float r, float g, float b, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index dec1178672..db534cc60a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1263,8 +1263,8 @@ void SurfaceFlinger::resyncWithRateLimit() { sLastResyncAttempted = now; } -void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, - hwc2_display_t displayId, int64_t timestamp) { +void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId, + int64_t timestamp) { Mutex::Autolock lock(mStateLock); // Ignore any vsyncs from a previous hardware composer. if (sequenceId != getBE().mComposerSequenceId) { @@ -1272,7 +1272,7 @@ void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, } int32_t type; - if (!getBE().mHwc->onVsync(displayId, timestamp, &type)) { + if (!getBE().mHwc->onVsync(hwcDisplayId, timestamp, &type)) { return; } @@ -1297,9 +1297,9 @@ void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) { *compositorTiming = getBE().mCompositorTiming; } -void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t display, +void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId, HWC2::Connection connection) { - ALOGV("onHotplugReceived(%d, %" PRIu64 ", %s)", sequenceId, display, + ALOGV("%s(%d, %" PRIu64 ", %s)", __FUNCTION__, sequenceId, hwcDisplayId, connection == HWC2::Connection::Connected ? "connected" : "disconnected"); // Ignore events that do not have the right sequenceId. @@ -1313,7 +1313,7 @@ void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t displa // acquire it here. ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId); - mPendingHotplugEvents.emplace_back(HotplugEvent{display, connection}); + mPendingHotplugEvents.emplace_back(HotplugEvent{hwcDisplayId, connection}); if (std::this_thread::get_id() == mMainThreadId) { // Process all pending hot plug events immediately if we are on the main thread. @@ -1323,8 +1323,7 @@ void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t displa setTransactionFlags(eDisplayTransactionNeeded); } -void SurfaceFlinger::onRefreshReceived(int sequenceId, - hwc2_display_t /*display*/) { +void SurfaceFlinger::onRefreshReceived(int sequenceId, hwc2_display_t /*hwcDisplayId*/) { Mutex::Autolock lock(mStateLock); if (sequenceId != getBE().mComposerSequenceId) { return; @@ -2135,9 +2134,9 @@ DisplayDevice::DisplayType SurfaceFlinger::determineDisplayType(hwc2_display_t h void SurfaceFlinger::processDisplayHotplugEventsLocked() { for (const auto& event : mPendingHotplugEvents) { - auto displayType = determineDisplayType(event.display, event.connection); + auto displayType = determineDisplayType(event.hwcDisplayId, event.connection); if (displayType == DisplayDevice::DISPLAY_ID_INVALID) { - ALOGW("Unable to determine the display type for display %" PRIu64, event.display); + ALOGW("Unable to determine the display type for display %" PRIu64, event.hwcDisplayId); continue; } @@ -2147,9 +2146,9 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { } const auto displayId = - getBE().mHwc->onHotplug(event.display, displayType, event.connection); + getBE().mHwc->onHotplug(event.hwcDisplayId, displayType, event.connection); if (displayId) { - ALOGV("Display %" PRIu64 " has stable ID %" PRIu64, event.display, *displayId); + ALOGV("Display %" PRIu64 " has stable ID %" PRIu64, event.hwcDisplayId, *displayId); } if (event.connection == HWC2::Connection::Connected) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 48c3f73bf6..87e0699aa0 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -457,11 +457,11 @@ private: /* ------------------------------------------------------------------------ * HWC2::ComposerCallback / HWComposer::EventHandler interface */ - void onVsyncReceived(int32_t sequenceId, hwc2_display_t display, + void onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId, int64_t timestamp) override; - void onHotplugReceived(int32_t sequenceId, hwc2_display_t display, + void onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId, HWC2::Connection connection) override; - void onRefreshReceived(int32_t sequenceId, hwc2_display_t display) override; + void onRefreshReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId) override; /* ------------------------------------------------------------------------ * Message handling @@ -665,8 +665,7 @@ private: void logLayerStats(); void doDisplayComposition(const sp& display, const Region& dirtyRegion); - // compose surfaces for display hw. this fails if using GL and the surface - // has been destroyed and is no longer valid. + // This fails if using GL and the surface has been destroyed. bool doComposeSurfaces(const sp& display); void postFramebuffer(); @@ -675,8 +674,8 @@ private: /* ------------------------------------------------------------------------ * Display management */ - DisplayDevice::DisplayType determineDisplayType(hwc2_display_t display, - HWC2::Connection connection) const; + DisplayDevice::DisplayType determineDisplayType(hwc2_display_t hwcDisplayId, + HWC2::Connection connection) const; sp setupNewDisplayDeviceInternal(const wp& displayToken, int32_t displayId, const DisplayDeviceState& state, @@ -802,7 +801,7 @@ private: bool mHadClientComposition = false; struct HotplugEvent { - hwc2_display_t display; + hwc2_display_t hwcDisplayId; HWC2::Connection connection = HWC2::Connection::Invalid; }; // protected by mStateLock diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index 1a7805aaf6..7928cba108 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -696,8 +696,8 @@ using InvalidDisplayCase = CasesetPowerMode(HWC_POWER_MODE_NORMAL); // -------------------------------------------------------------------- diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 2f22989897..ae5a1004c0 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -91,8 +91,9 @@ public: auto onInitializeDisplays() { return mFlinger->onInitializeDisplays(); } - auto setPowerModeInternal(const sp& hw, int mode, bool stateLockHeld = false) { - return mFlinger->setPowerModeInternal(hw, mode, stateLockHeld); + auto setPowerModeInternal(const sp& display, int mode, + bool stateLockHeld = false) { + return mFlinger->setPowerModeInternal(display, mode, stateLockHeld); } /* ------------------------------------------------------------------------ -- cgit v1.2.3-59-g8ed1b From 436ccf3f42b20bf39ac23736cb0fe7533ef4afcc Mon Sep 17 00:00:00 2001 From: Dan Stoza Date: Thu, 21 Jun 2018 12:10:12 -0700 Subject: SF: Add GL texture pool Adds a pool of GL texture names. Prior to this change, Layer creation was forced to run on the SF main thread because it would need to call into RenderEngine to generate a new texture name. By creating a pool of pre-generated texture names, this operation no longer needs to run on the main thread, which unblocks the rest of the system during operations such as fingerprint unlock. Bug: 110477323 Test: SurfaceFlinger_test + manual: examine systrace and observe that layer creation no longer blocks on access to the main thread Change-Id: I9d68874d6c6f704c8884676454e84d916cd86507 --- services/surfaceflinger/BufferLayer.cpp | 9 ++++-- services/surfaceflinger/Client.cpp | 44 ++---------------------------- services/surfaceflinger/ContainerLayer.h | 2 ++ services/surfaceflinger/Layer.cpp | 21 ++++++++++---- services/surfaceflinger/Layer.h | 5 ++++ services/surfaceflinger/SurfaceFlinger.cpp | 37 ++++++++++++++++++++++++- services/surfaceflinger/SurfaceFlinger.h | 11 ++++++++ 7 files changed, 78 insertions(+), 51 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index aae393155a..e128df700b 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -63,7 +63,7 @@ BufferLayer::BufferLayer(SurfaceFlinger* flinger, const sp& client, cons mRefreshPending(false) { ALOGV("Creating Layer %s", name.string()); - mFlinger->getRenderEngine().genTextures(1, &mTextureName); + mTextureName = mFlinger->getNewTexture(); mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName); if (flags & ISurfaceComposerClient::eNonPremultiplied) mPremultipliedAlpha = false; @@ -701,7 +701,12 @@ void BufferLayer::onFirstRef() { sp consumer; BufferQueue::createBufferQueue(&producer, &consumer, true); mProducer = new MonitoredProducer(producer, mFlinger, this); - mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this); + { + // Grab the SF state lock during this since it's the only safe way to access RenderEngine + Mutex::Autolock lock(mFlinger->mStateLock); + mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, + this); + } mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); mConsumer->setContentsChangedListener(this); mConsumer->setName(mName); diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index 077469b5e1..0b59147c5a 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -170,48 +170,8 @@ status_t Client::createSurface( } } - /* - * createSurface must be called from the GL thread so that it can - * have access to the GL context. - */ - class MessageCreateLayer : public MessageBase { - SurfaceFlinger* flinger; - Client* client; - sp* handle; - sp* gbp; - status_t result; - const String8& name; - uint32_t w, h; - PixelFormat format; - uint32_t flags; - sp* parent; - int32_t windowType; - int32_t ownerUid; - public: - MessageCreateLayer(SurfaceFlinger* flinger, - const String8& name, Client* client, - uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - sp* handle, int32_t windowType, int32_t ownerUid, - sp* gbp, - sp* parent) - : flinger(flinger), client(client), - handle(handle), gbp(gbp), result(NO_ERROR), - name(name), w(w), h(h), format(format), flags(flags), - parent(parent), windowType(windowType), ownerUid(ownerUid) { - } - status_t getResult() const { return result; } - virtual bool handler() { - result = flinger->createLayer(name, client, w, h, format, flags, - windowType, ownerUid, handle, gbp, parent); - return true; - } - }; - - sp msg = new MessageCreateLayer(mFlinger.get(), - name, this, w, h, format, flags, handle, - windowType, ownerUid, gbp, &parent); - mFlinger->postMessageSync(msg); - return static_cast( msg.get() )->getResult(); + return mFlinger->createLayer(name, this, w, h, format, flags, windowType, + ownerUid, handle, gbp, &parent); } status_t Client::destroySurface(const sp& handle) { diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index 84b75f4f09..06cfbcd894 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -35,6 +35,8 @@ public: bool isVisible() const override; void setPerFrameData(const sp& display) override; + + bool isCreatedFromMainThread() const override { return true; } }; } // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index b4b3f4ad0b..268879c923 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -127,17 +127,26 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n // drawing state & current state are identical mDrawingState = mCurrentState; - const auto& hwc = flinger->getHwComposer(); - const auto& activeConfig = hwc.getActiveConfig(HWC_DISPLAY_PRIMARY); - nsecs_t displayPeriod = activeConfig->getVsyncPeriod(); - mFrameTracker.setDisplayRefreshPeriod(displayPeriod); - CompositorTiming compositorTiming; flinger->getCompositorTiming(&compositorTiming); mFrameEventHistory.initializeCompositorTiming(compositorTiming); } -void Layer::onFirstRef() {} +void Layer::onFirstRef() NO_THREAD_SAFETY_ANALYSIS { + if (!isCreatedFromMainThread()) { + // Grab the SF state lock during this since it's the only way to safely access HWC + mFlinger->mStateLock.lock(); + } + + const auto& hwc = mFlinger->getHwComposer(); + const auto& activeConfig = hwc.getActiveConfig(HWC_DISPLAY_PRIMARY); + nsecs_t displayPeriod = activeConfig->getVsyncPeriod(); + mFrameTracker.setDisplayRefreshPeriod(displayPeriod); + + if (!isCreatedFromMainThread()) { + mFlinger->mStateLock.unlock(); + } +} Layer::~Layer() { sp c(mClientRef.promote()); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index fb94058d0d..4baf56c76e 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -297,6 +297,11 @@ public: */ virtual bool isFixedSize() const { return true; } + // Most layers aren't created from the main thread, and therefore need to + // grab the SF state lock to access HWC, but ContainerLayer does, so we need + // to avoid grabbing the lock again to avoid deadlock + virtual bool isCreatedFromMainThread() const { return false; } + bool isPendingRemoval() const { return mPendingRemoval; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e39e62343f..196c6ea584 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -501,6 +501,27 @@ void SurfaceFlinger::bootFinished() postMessageAsync(new LambdaMessage([this] { readPersistentProperties(); })); } +uint32_t SurfaceFlinger::getNewTexture() { + { + std::lock_guard lock(mTexturePoolMutex); + if (!mTexturePool.empty()) { + uint32_t name = mTexturePool.back(); + mTexturePool.pop_back(); + ATRACE_INT("TexturePoolSize", mTexturePool.size()); + return name; + } + + // The pool was too small, so increase it for the future + ++mTexturePoolSize; + } + + // The pool was empty, so we need to get a new texture name directly using a + // blocking call to the main thread + uint32_t name = 0; + postMessageSync(new LambdaMessage([&]() { getRenderEngine().genTextures(1, &name); })); + return name; +} + void SurfaceFlinger::deleteTextureAsync(uint32_t texture) { postMessageAsync(new LambdaMessage([=] { getRenderEngine().deleteTextures(1, &texture); })); } @@ -1758,6 +1779,17 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) getBE().mTotalTime += elapsedTime; } getBE().mLastSwapTime = currentTime; + + { + std::lock_guard lock(mTexturePoolMutex); + const size_t refillCount = mTexturePoolSize - mTexturePool.size(); + if (refillCount > 0) { + const size_t offset = mTexturePool.size(); + mTexturePool.resize(mTexturePoolSize); + getRenderEngine().genTextures(refillCount, mTexturePool.data() + offset); + ATRACE_INT("TexturePoolSize", mTexturePool.size()); + } + } } void SurfaceFlinger::rebuildLayerStacks() { @@ -3515,10 +3547,13 @@ String8 SurfaceFlinger::getUniqueLayerName(const String8& name) // Tack on our counter whether there is a hit or not, so everyone gets a tag String8 uniqueName = name + "#" + String8(std::to_string(dupeCounter).c_str()); + // Grab the state lock since we're accessing mCurrentState + Mutex::Autolock lock(mStateLock); + // Loop over layers until we're sure there is no matching name while (matchFound) { matchFound = false; - mDrawingState.traverseInZOrder([&](Layer* layer) { + mCurrentState.traverseInZOrder([&](Layer* layer) { if (layer->getName() == uniqueName) { matchFound = true; uniqueName = name + "#" + String8(std::to_string(++dupeCounter).c_str()); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 87e0699aa0..2e9062e1fd 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -322,6 +322,10 @@ public: return getDefaultDisplayDeviceLocked(); } + // Obtains a name from the texture pool, or, if the pool is empty, posts a + // synchronous message to the main thread to obtain one on the fly + uint32_t getNewTexture(); + // utility function to delete a texture on the main thread void deleteTextureAsync(uint32_t texture); @@ -851,6 +855,13 @@ private: std::atomic mRefreshPending{false}; + // We maintain a pool of pre-generated texture names to hand out to avoid + // layer creation needing to run on the main thread (which it would + // otherwise need to do to access RenderEngine). + std::mutex mTexturePoolMutex; + uint32_t mTexturePoolSize = 0; + std::vector mTexturePool; + /* ------------------------------------------------------------------------ * Feature prototyping */ -- cgit v1.2.3-59-g8ed1b From adc40c22a3fe569884621fdac2f2ea8f7927a9bc Mon Sep 17 00:00:00 2001 From: chaviw Date: Tue, 10 Jul 2018 16:57:27 -0700 Subject: Add current frame and barrier layer info to protobuf. Added more info to the protobuf to help identify the root cause of the bug. Bug: 111062294 Test: go/winscope Change-Id: Ife93907482ad89341b20a5508acce04ad4a5b32e --- services/surfaceflinger/Layer.cpp | 10 ++++++++++ services/surfaceflinger/layerproto/layers.proto | 11 +++++++++++ 2 files changed, 21 insertions(+) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 11c3db0228..40d89bdb10 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2004,6 +2004,16 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) layerInfo->set_refresh_pending(isBufferLatched()); layerInfo->set_window_type(state.type); layerInfo->set_app_id(state.appId); + layerInfo->set_curr_frame(mCurrentFrameNumber); + + for (const auto& pendingState : mPendingStates) { + auto barrierLayer = pendingState.barrierLayer.promote(); + if (barrierLayer != nullptr) { + BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer(); + barrierLayerProto->set_id(barrierLayer->sequence); + barrierLayerProto->set_frame_number(pendingState.frameNumber); + } + } } void Layer::writeToProto(LayerProto* layerInfo, int32_t displayId) { diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index eb346944af..e34772fd4f 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -82,6 +82,10 @@ message LayerProto { optional bool is_protected = 36; // If active_buffer is not null, record its transform optional TransformProto buffer_transform = 37; + // Current frame number being rendered. + optional uint64 curr_frame = 38; + // A list of barriers that the layer is waiting to update state. + repeated BarrierLayerProto barrier_layer = 39; } message PositionProto { @@ -133,3 +137,10 @@ message ColorProto { optional float b = 3; optional float a = 4; } + +message BarrierLayerProto { + // layer id the barrier is waiting on. + optional int32 id = 1; + // frame number the barrier is waiting on. + optional uint64 frame_number = 2; +} -- cgit v1.2.3-59-g8ed1b From 0756cdd4b9cef33107ed13763d7168bc3363fae9 Mon Sep 17 00:00:00 2001 From: David Sodman Date: Fri, 13 Apr 2018 11:26:33 -0700 Subject: Revert "surfacefligner: revert recent BE/FE split changes" This reverts commit 30505fb0e0f71b88eeed618200c35f9518144060. Test: Manual and cts -m ViewTestCases Change-Id: I8fb39243827b61baeba9bc30f9b70cf782dcb4b2 --- services/surfaceflinger/BufferLayer.cpp | 58 +---- services/surfaceflinger/ColorLayer.cpp | 37 +-- services/surfaceflinger/Layer.cpp | 62 ++--- services/surfaceflinger/Layer.h | 8 + services/surfaceflinger/LayerBE.h | 6 +- services/surfaceflinger/SurfaceFlinger.cpp | 360 +++++++++++++++++++++-------- services/surfaceflinger/SurfaceFlinger.h | 26 ++- 7 files changed, 333 insertions(+), 224 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 37f4b0f007..75d8942f69 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -633,37 +633,14 @@ void BufferLayer::setPerFrameData(const sp& display) { const auto& viewport = display->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); const auto displayId = display->getId(); - if (!hasHwcLayer(displayId)) { - ALOGE("[%s] failed to setPerFrameData: no HWC layer found (%d)", - mName.string(), displayId); - return; - } - auto& hwcInfo = getBE().mHwcLayers[displayId]; - 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(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(error)); - surfaceDamageRegion.dump(LOG_TAG); - } + getBE().compositionInfo.hwc.visibleRegion = visible; + getBE().compositionInfo.hwc.surfaceDamage = surfaceDamageRegion; // Sideband layers if (getBE().compositionInfo.hwc.sidebandStream.get()) { setCompositionType(displayId, HWC2::Composition::Sideband); - ALOGV("[%s] Requesting Sideband composition", mName.string()); - error = hwcLayer->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle()); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(), - getBE().compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(), - static_cast(error)); - } + getBE().compositionInfo.compositionType = HWC2::Composition::Sideband; return; } @@ -676,31 +653,14 @@ void BufferLayer::setPerFrameData(const sp& display) { setCompositionType(displayId, HWC2::Composition::Device); } - ALOGV("setPerFrameData: dataspace = %d", mCurrentDataSpace); - error = hwcLayer->setDataspace(mCurrentDataSpace); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace, - to_string(error).c_str(), static_cast(error)); - } - - const HdrMetadata& metadata = mConsumer->getCurrentHdrMetadata(); - error = hwcLayer->setPerFrameMetadata(display->getSupportedPerFrameMetadata(), metadata); - if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) { - ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast(error)); - } - - uint32_t hwcSlot = 0; - sp hwcBuffer; - hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, &hwcSlot, &hwcBuffer); + getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace; + getBE().compositionInfo.hwc.hdrMetadata = mConsumer->getCurrentHdrMetadata(); + getBE().compositionInfo.hwc.supportedPerFrameMetadata = display->getSupportedPerFrameMetadata(); auto acquireFence = mConsumer->getCurrentFence(); - error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), - getBE().compositionInfo.mBuffer->handle, to_string(error).c_str(), - static_cast(error)); - } + getBE().compositionInfo.mBufferSlot = mActiveBufferSlot; + getBE().compositionInfo.mBuffer = mActiveBuffer; + getBE().compositionInfo.hwc.fence = acquireFence; } bool BufferLayer::isOpaque(const Layer::State& s) const { diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 8515fcf6ce..bf4a859c53 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -77,43 +77,18 @@ void ColorLayer::setPerFrameData(const sp& display) { const auto& viewport = display->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); const auto displayId = display->getId(); - if (!hasHwcLayer(displayId)) { - ALOGE("[%s] failed to setPerFrameData: no HWC layer found (%d)", - mName.string(), displayId); - return; - } - auto& hwcInfo = getBE().mHwcLayers[displayId]; - 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(error)); - visible.dump(LOG_TAG); - } + getBE().compositionInfo.hwc.visibleRegion = visible; + getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace; setCompositionType(displayId, HWC2::Composition::SolidColor); - error = hwcLayer->setDataspace(mCurrentDataSpace); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace, - to_string(error).c_str(), static_cast(error)); - } - half4 color = getColor(); - error = hwcLayer->setColor({static_cast(std::round(255.0f * color.r)), - static_cast(std::round(255.0f * color.g)), - static_cast(std::round(255.0f * color.b)), 255}); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set color: %s (%d)", mName.string(), to_string(error).c_str(), - static_cast(error)); - } + getBE().compositionInfo.hwc.color = { static_cast(std::round(255.0f * color.r)), + static_cast(std::round(255.0f * color.g)), + static_cast(std::round(255.0f * color.b)), 255 }; // 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(error)); - } + getBE().compositionInfo.hwc.transform = HWC2::Transform::None; } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 40d89bdb10..4eedb1a13d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -503,6 +503,9 @@ void Layer::setGeometry(const sp& display, uint32_t z) { } auto& hwcInfo = getBE().mHwcLayers[displayId]; + // Need to program geometry parts + getBE().compositionInfo.hwc.skipGeometry = false; + // enable this layer hwcInfo.forceClientComposition = false; @@ -510,8 +513,6 @@ void Layer::setGeometry(const sp& display, uint32_t z) { hwcInfo.forceClientComposition = true; } - auto& hwcLayer = hwcInfo.layer; - // this gives us only the "orientation" component of the transform const State& s(getDrawingState()); auto blendMode = HWC2::BlendMode::None; @@ -519,12 +520,7 @@ void Layer::setGeometry(const sp& display, uint32_t z) { 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(error)); + getBE().compositionInfo.hwc.blendMode = blendMode; // apply the layer's transform, followed by the display's global transform // here we're guaranteed that the layer's transform preserves rects @@ -567,36 +563,15 @@ void Layer::setGeometry(const sp& display, uint32_t z) { } const Transform& tr = display->getTransform(); 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(error)); - } else { - hwcInfo.displayFrame = transformedFrame; - } + getBE().compositionInfo.hwc.displayFrame = transformedFrame; FloatRect sourceCrop = computeCrop(display); - 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(error)); - } else { - hwcInfo.sourceCrop = sourceCrop; - } + getBE().compositionInfo.hwc.sourceCrop = sourceCrop; float alpha = static_cast(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(error)); + getBE().compositionInfo.hwc.alpha = alpha; - 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(error)); + getBE().compositionInfo.hwc.z = z; int type = s.type; int appId = s.appId; @@ -609,9 +584,8 @@ void Layer::setGeometry(const sp& display, uint32_t z) { } } - error = hwcLayer->setInfo(type, appId); - ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)", mName.string(), - static_cast(error)); + getBE().compositionInfo.hwc.type = type; + getBE().compositionInfo.hwc.appId = appId; /* * Transformations are applied in this order: @@ -648,16 +622,11 @@ void Layer::setGeometry(const sp& display, uint32_t z) { const uint32_t orientation = transform.getOrientation(); if (orientation & Transform::ROT_INVALID) { // we can only handle simple transformation - hwcInfo.forceClientComposition = true; + getBE().mHwcLayers[displayId].compositionType = HWC2::Composition::Client; } else { auto transform = static_cast(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(error)); + getBE().compositionInfo.hwc.transform = transform; } } @@ -1498,17 +1467,16 @@ void Layer::miniDump(String8& result, int32_t displayId) const { result.appendFormat(" %s\n", name.string()); const Layer::State& layerState(getDrawingState()); - const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(displayId); if (layerState.zOrderRelativeOf != nullptr || mDrawingParent != nullptr) { result.appendFormat(" rel %6d | ", layerState.z); } else { result.appendFormat(" %10d | ", layerState.z); } result.appendFormat("%10s | ", to_string(getCompositionType(displayId)).c_str()); - result.appendFormat("%10s | ", to_string(hwcInfo.transform).c_str()); - const Rect& frame = hwcInfo.displayFrame; + result.appendFormat("%10s | ", to_string(getBE().mHwcLayers[displayId].transform).c_str()); + const Rect& frame = getBE().compositionInfo.hwc.displayFrame; result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom); - const FloatRect& crop = hwcInfo.sourceCrop; + const FloatRect& crop = getBE().compositionInfo.hwc.sourceCrop; result.appendFormat("%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top, crop.right, crop.bottom); result.append("- - - - - - - - - - - - - - - -"); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index f72409652d..5107e6b32d 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -472,6 +472,14 @@ public: return getBE().mHwcLayers[displayId].layer; } + bool setHwcLayer(int32_t hwcId) { + if (getBE().mHwcLayers.count(hwcId) == 0) { + return false; + } + getBE().compositionInfo.hwc.hwcLayer = getBE().mHwcLayers[hwcId].layer; + return true; + } + // ----------------------------------------------------------------------- void clearWithOpenGL(const RenderArea& renderArea) const; diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 9aa43f7fd3..680fbd049c 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -19,10 +19,9 @@ #include #include +#include #include -#include "SurfaceFlinger.h" - #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/HWComposerBufferCache.h" #include "RenderEngine/Mesh.h" @@ -40,6 +39,7 @@ struct CompositionInfo { LayerBE* layer = nullptr; struct { HWC2::Layer* hwcLayer; + bool skipGeometry = true; sp fence; HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid; Rect displayFrame; @@ -54,6 +54,8 @@ struct CompositionInfo { sp sidebandStream; ui::Dataspace dataspace; hwc_color_t color; + bool supportedPerFrameMetadata = false; + HdrMetadata hdrMetadata; } hwc; struct { Mesh* mesh; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 085dcc2683..f41102f556 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -777,6 +777,7 @@ void SurfaceFlinger::init() { // set initial conditions (e.g. unblank default device) initializeDisplays(); + ALOGV("Displays initialized"); getBE().mRenderEngine->primeCache(); @@ -1525,7 +1526,13 @@ void SurfaceFlinger::onMessageReceived(int32_t what) { bool refreshNeeded = handleMessageTransaction(); refreshNeeded |= handleMessageInvalidate(); refreshNeeded |= mRepaintEverything; + + preComposition(); + rebuildLayerStacks(); + calculateWorkingSet(); + if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) { + // Signal a refresh if a transaction modified the window state, // a new buffer was latched, or if HWC has requested a full // repaint @@ -1554,21 +1561,112 @@ bool SurfaceFlinger::handleMessageInvalidate() { return handlePageFlip(); } +void SurfaceFlinger::calculateWorkingSet() { + ATRACE_CALL(); + ALOGV(__FUNCTION__); + + // build the h/w work list + if (CC_UNLIKELY(mGeometryInvalid)) { + mGeometryInvalid = false; + for (const auto& [token, display] : mDisplays) { + const auto displayId = display->getId(); + if (displayId >= 0) { + const Vector>& currentLayers( + display->getVisibleLayersSortedByZ()); + for (size_t i = 0; i < currentLayers.size(); i++) { + const auto& layer = currentLayers[i]; + + if (!layer->hasHwcLayer(displayId)) { + if (!layer->createHwcLayer(getBE().mHwc.get(), displayId)) { + layer->forceClientComposition(displayId); + continue; + } + } + + layer->setGeometry(display, i); + if (mDebugDisableHWC || mDebugRegion) { + layer->forceClientComposition(displayId); + } + } + } + } + } + + // Set the per-frame data + for (const auto& [token, display] : mDisplays) { + const auto displayId = display->getId(); + if (displayId < 0) { + continue; + } + + if (mDrawingState.colorMatrixChanged) { + display->setColorTransform(mDrawingState.colorMatrix); + status_t result = getBE().mHwc->setColorTransform(displayId, mDrawingState.colorMatrix); + ALOGE_IF(result != NO_ERROR, "Failed to set color transform on " + "display %d: %d", displayId, result); + } + for (auto& layer : display->getVisibleLayersSortedByZ()) { + if (layer->isHdrY410()) { + layer->forceClientComposition(displayId); + } else if ((layer->getDataSpace() == Dataspace::BT2020_PQ || + layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) && + !display->hasHDR10Support()) { + layer->forceClientComposition(displayId); + } else if ((layer->getDataSpace() == Dataspace::BT2020_HLG || + layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) && + !display->hasHLGSupport()) { + layer->forceClientComposition(displayId); + } + + if (layer->getForceClientComposition(displayId)) { + ALOGV("[%s] Requesting Client composition", layer->getName().string()); + layer->setCompositionType(displayId, HWC2::Composition::Client); + continue; + } + + layer->setPerFrameData(display); + } + + if (hasWideColorDisplay) { + ColorMode colorMode; + Dataspace dataSpace; + RenderIntent renderIntent; + pickColorMode(display, &colorMode, &dataSpace, &renderIntent); + setActiveColorModeInternal(display, colorMode, dataSpace, renderIntent); + } + } + + mDrawingState.colorMatrixChanged = false; + getBE().mCompositionInfo.clear(); + + for (const auto& [token, display] : mDisplays) { + for (auto& layer : display->getVisibleLayersSortedByZ()) { + auto displayId = display->getId(); + layer->getBE().compositionInfo.compositionType = layer->getCompositionType(displayId); + if (!layer->setHwcLayer(displayId)) { + ALOGV("Need to create HWCLayer for %s", layer->getName().string()); + } + getBE().mCompositionInfo.push_back(layer->getBE().compositionInfo); + layer->getBE().compositionInfo.hwc.hwcLayer = nullptr; + } + } +} + void SurfaceFlinger::handleMessageRefresh() { ATRACE_CALL(); mRefreshPending = false; - nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC); - - preComposition(refreshStartTime); - rebuildLayerStacks(); - setUpHWComposer(); + beginFrame(); + for (auto compositionInfo : getBE().mCompositionInfo) { + setUpHWComposer(compositionInfo); + } + prepareFrame(); doDebugFlashRegions(); doTracing("handleRefresh"); logLayerStats(); doComposition(); - postComposition(refreshStartTime); + postComposition(); mHadClientComposition = false; for (const auto& [token, display] : mDisplays) { @@ -1644,14 +1742,14 @@ void SurfaceFlinger::logLayerStats() { } } -void SurfaceFlinger::preComposition(nsecs_t refreshStartTime) +void SurfaceFlinger::preComposition() { ATRACE_CALL(); ALOGV("preComposition"); bool needExtraInvalidate = false; mDrawingState.traverseInZOrder([&](Layer* layer) { - if (layer->onPreComposition(refreshStartTime)) { + if (layer->onPreComposition(mRefreshStartTime)) { needExtraInvalidate = true; } }); @@ -1720,7 +1818,7 @@ void SurfaceFlinger::setCompositorTimingSnapped(nsecs_t vsyncPhase, getBE().mCompositorTiming.presentLatency = snappedCompositeToPresentLatency; } -void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) +void SurfaceFlinger::postComposition() { ATRACE_CALL(); ALOGV("postComposition"); @@ -1753,11 +1851,11 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0); nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod(); - // We use the refreshStartTime which might be sampled a little later than + // We use the mRefreshStartTime which might be sampled a little later than // when we started doing work for this frame, but that should be okay // since updateCompositorTiming has snapping logic. updateCompositorTiming( - vsyncPhase, vsyncInterval, refreshStartTime, presentFenceTime); + vsyncPhase, vsyncInterval, mRefreshStartTime, presentFenceTime); CompositorTiming compositorTiming; { std::lock_guard lock(getBE().mCompositorTimingLock); @@ -1869,15 +1967,21 @@ void SurfaceFlinger::rebuildLayerStacks() { if (!drawRegion.isEmpty()) { layersSortedByZ.add(layer); } else { - // Clear out the HWC layer if this layer was - // previously visible, but no longer is - hwcLayerDestroyed = layer->destroyHwcLayer(display->getId()); + if (layer->hasHwcLayer(display->getId())) { + // Clear out the HWC layer if this layer was + // previously visible, but no longer is + hwcLayerDestroyed = layer->destroyHwcLayer( + display->getId()); + } } } else { - // WM changes display->layerStack upon sleep/awake. - // Here we make sure we delete the HWC layers even if - // WM changed their layer stack. - hwcLayerDestroyed = layer->destroyHwcLayer(display->getId()); + if (layer->hasHwcLayer(display->getId())) { + // WM changes display->layerStack upon sleep/awake. + // Here we make sure we delete the HWC layers even if + // WM changed their layer stack. + hwcLayerDestroyed = layer->destroyHwcLayer( + display->getId()); + } } // If a layer is not going to get a release fence because @@ -1979,9 +2083,124 @@ void SurfaceFlinger::pickColorMode(const sp& display, ColorMode* display->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent); } -void SurfaceFlinger::setUpHWComposer() { - ATRACE_CALL(); - ALOGV("setUpHWComposer"); +void SurfaceFlinger::configureSidebandComposition(const CompositionInfo& compositionInfo) const +{ + HWC2::Error error; + LOG_ALWAYS_FATAL_IF(compositionInfo.hwc.sidebandStream == nullptr, + "CompositionType is sideband, but sideband stream is nullptr"); + error = (compositionInfo.hwc.hwcLayer) + ->setSidebandStream(compositionInfo.hwc.sidebandStream->handle()); + if (error != HWC2::Error::None) { + ALOGE("[SF] Failed to set sideband stream %p: %s (%d)", + compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(), + static_cast(error)); + } +} + +void SurfaceFlinger::configureHwcCommonData(const CompositionInfo& compositionInfo) const +{ + HWC2::Error error; + + if (!compositionInfo.hwc.skipGeometry) { + error = (compositionInfo.hwc.hwcLayer)->setBlendMode(compositionInfo.hwc.blendMode); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set blend mode %s:" + " %s (%d)", + to_string(compositionInfo.hwc.blendMode).c_str(), to_string(error).c_str(), + static_cast(error)); + + error = (compositionInfo.hwc.hwcLayer)->setDisplayFrame(compositionInfo.hwc.displayFrame); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set the display frame [%d, %d, %d, %d] %s (%d)", + compositionInfo.hwc.displayFrame.left, + compositionInfo.hwc.displayFrame.right, + compositionInfo.hwc.displayFrame.top, + compositionInfo.hwc.displayFrame.bottom, + to_string(error).c_str(), static_cast(error)); + + error = (compositionInfo.hwc.hwcLayer)->setSourceCrop(compositionInfo.hwc.sourceCrop); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: %s (%d)", + compositionInfo.hwc.sourceCrop.left, + compositionInfo.hwc.sourceCrop.right, + compositionInfo.hwc.sourceCrop.top, + compositionInfo.hwc.sourceCrop.bottom, + to_string(error).c_str(), static_cast(error)); + + error = (compositionInfo.hwc.hwcLayer)->setPlaneAlpha(compositionInfo.hwc.alpha); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set plane alpha %.3f: " + "%s (%d)", + compositionInfo.hwc.alpha, + to_string(error).c_str(), static_cast(error)); + + + error = (compositionInfo.hwc.hwcLayer)->setZOrder(compositionInfo.hwc.z); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set Z %u: %s (%d)", + compositionInfo.hwc.z, + to_string(error).c_str(), static_cast(error)); + + error = (compositionInfo.hwc.hwcLayer) + ->setInfo(compositionInfo.hwc.type, compositionInfo.hwc.appId); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set info (%d)", + static_cast(error)); + + error = (compositionInfo.hwc.hwcLayer)->setTransform(compositionInfo.hwc.transform); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set transform %s: " + "%s (%d)", + to_string(compositionInfo.hwc.transform).c_str(), to_string(error).c_str(), + static_cast(error)); + } + + error = (compositionInfo.hwc.hwcLayer)->setCompositionType(compositionInfo.compositionType); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set composition type: %s (%d)", + to_string(error).c_str(), static_cast(error)); + + error = (compositionInfo.hwc.hwcLayer)->setDataspace(compositionInfo.hwc.dataspace); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set dataspace: %s (%d)", + to_string(error).c_str(), static_cast(error)); + + error = (compositionInfo.hwc.hwcLayer)->setPerFrameMetadata( + compositionInfo.hwc.supportedPerFrameMetadata, compositionInfo.hwc.hdrMetadata); + ALOGE_IF(error != HWC2::Error::None && error != HWC2::Error::Unsupported, + "[SF] Failed to set hdrMetadata: %s (%d)", + to_string(error).c_str(), static_cast(error)); + + error = (compositionInfo.hwc.hwcLayer)->setColor(compositionInfo.hwc.color); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set color: %s (%d)", + to_string(error).c_str(), static_cast(error)); + + error = (compositionInfo.hwc.hwcLayer)->setVisibleRegion(compositionInfo.hwc.visibleRegion); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set visible region: %s (%d)", + to_string(error).c_str(), static_cast(error)); +} + +void SurfaceFlinger::configureDeviceComposition(const CompositionInfo& compositionInfo) const +{ + HWC2::Error error; + + error = (compositionInfo.hwc.hwcLayer)->setSurfaceDamage(compositionInfo.hwc.surfaceDamage); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set surface damage: %s (%d)", + to_string(error).c_str(), static_cast(error)); + + error = (compositionInfo.hwc.hwcLayer)->setBuffer(compositionInfo.mBufferSlot, + compositionInfo.mBuffer, compositionInfo.hwc.fence); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set buffer: %s (%d)", + to_string(error).c_str(), static_cast(error)); +} + +void SurfaceFlinger::beginFrame() +{ + mRefreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC); for (const auto& [token, display] : mDisplays) { bool dirty = !display->getDirtyRegion(mRepaintEverything).isEmpty(); @@ -2008,86 +2227,44 @@ void SurfaceFlinger::setUpHWComposer() { display->lastCompositionHadVisibleLayers = !empty; } } +} - // build the h/w work list - if (CC_UNLIKELY(mGeometryInvalid)) { - mGeometryInvalid = false; - for (const auto& [token, display] : mDisplays) { - const auto displayId = display->getId(); - if (displayId >= 0) { - const Vector>& currentLayers = display->getVisibleLayersSortedByZ(); - for (size_t i = 0; i < currentLayers.size(); i++) { - const auto& layer = currentLayers[i]; - if (!layer->hasHwcLayer(displayId)) { - if (!layer->createHwcLayer(getBE().mHwc.get(), displayId)) { - layer->forceClientComposition(displayId); - continue; - } - } - - layer->setGeometry(display, i); - if (mDebugDisableHWC || mDebugRegion) { - layer->forceClientComposition(displayId); - } - } - } - } - } - - // Set the per-frame data +void SurfaceFlinger::prepareFrame() +{ for (const auto& [token, display] : mDisplays) { - const auto displayId = display->getId(); - if (displayId < 0) { + if (!display->isPoweredOn()) { continue; } - if (mDrawingState.colorMatrixChanged) { - display->setColorTransform(mDrawingState.colorMatrix); - status_t result = getBE().mHwc->setColorTransform(displayId, mDrawingState.colorMatrix); - ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display %d: %d", - displayId, result); - } - for (auto& layer : display->getVisibleLayersSortedByZ()) { - if (layer->isHdrY410()) { - layer->forceClientComposition(displayId); - } else if ((layer->getDataSpace() == Dataspace::BT2020_PQ || - layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) && - !display->hasHDR10Support()) { - layer->forceClientComposition(displayId); - } else if ((layer->getDataSpace() == Dataspace::BT2020_HLG || - layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) && - !display->hasHLGSupport()) { - layer->forceClientComposition(displayId); - } - - if (layer->getForceClientComposition(displayId)) { - ALOGV("[%s] Requesting Client composition", layer->getName().string()); - layer->setCompositionType(displayId, HWC2::Composition::Client); - continue; - } + status_t result = display->prepareFrame(*getBE().mHwc); + ALOGE_IF(result != NO_ERROR, "prepareFrame for display %d failed: %d (%s)", + display->getId(), result, strerror(-result)); + } +} - layer->setPerFrameData(display); - } +void SurfaceFlinger::setUpHWComposer(const CompositionInfo& compositionInfo) { + ATRACE_CALL(); + ALOGV("setUpHWComposer"); - if (hasWideColorDisplay) { - ColorMode colorMode; - Dataspace dataSpace; - RenderIntent renderIntent; - pickColorMode(display, &colorMode, &dataSpace, &renderIntent); - setActiveColorModeInternal(display, colorMode, dataSpace, renderIntent); - } - } + switch (compositionInfo.compositionType) + { + case HWC2::Composition::Invalid: + case HWC2::Composition::Client: + break; - mDrawingState.colorMatrixChanged = false; + case HWC2::Composition::Sideband: + configureSidebandComposition(compositionInfo); + break; - for (const auto& [token, display] : mDisplays) { - if (!display->isPoweredOn()) { - continue; - } + case HWC2::Composition::SolidColor: + configureHwcCommonData(compositionInfo); + break; - status_t result = display->prepareFrame(*getBE().mHwc); - ALOGE_IF(result != NO_ERROR, "prepareFrame for display %d failed: %d (%s)", - display->getId(), result, strerror(-result)); + case HWC2::Composition::Device: + case HWC2::Composition::Cursor: + configureHwcCommonData(compositionInfo); + configureDeviceComposition(compositionInfo); + break; } } @@ -5244,7 +5421,6 @@ void SurfaceFlinger::traverseLayersInDisplay(const sp& disp }; // namespace android - #if defined(__gl_h_) #error "don't include gl/gl.h in this file" #endif diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index e107f425be..2978b7fe89 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -225,6 +225,8 @@ public: // use to differentiate callbacks from different hardware composer // instances. Each hardware composer instance gets a different sequence id. int32_t mComposerSequenceId; + + std::vector mCompositionInfo; }; @@ -643,8 +645,8 @@ private: void computeVisibleRegions(const sp& display, Region& dirtyRegion, Region& opaqueRegion); - void preComposition(nsecs_t refreshStartTime); - void postComposition(nsecs_t refreshStartTime); + void preComposition(); + void postComposition(); void updateCompositorTiming( nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime, std::shared_ptr& presentFenceTime); @@ -662,7 +664,19 @@ private: void pickColorMode(const sp& display, ui::ColorMode* outMode, ui::Dataspace* outDataSpace, ui::RenderIntent* outRenderIntent) const; - void setUpHWComposer(); + void calculateWorkingSet(); + /* + * beginFrame - This function handles any pre-frame processing that needs to be + * prior to any CompositionInfo handling and is not dependent on data in + * CompositionInfo + */ + void beginFrame(); + /* prepareFrame - This function will call into the DisplayDevice to prepare a + * frame after CompositionInfo has been programmed. This provides a mechanism + * to prepare the hardware composer + */ + void prepareFrame(); + void setUpHWComposer(const CompositionInfo& compositionInfo); void doComposition(); void doDebugFlashRegions(); void doTracing(const char* where); @@ -780,6 +794,11 @@ private: // access must be protected by mInvalidateLock volatile int32_t mRepaintEverything; + // helper methods + void configureHwcCommonData(const CompositionInfo& compositionInfo) const; + void configureDeviceComposition(const CompositionInfo& compositionInfo) const; + void configureSidebandComposition(const CompositionInfo& compositionInfo) const; + // constant members (no synchronization needed for access) nsecs_t mBootTime; bool mGpuToCpuSupported; @@ -858,6 +877,7 @@ private: Mutex mHWVsyncLock; bool mPrimaryHWVsyncEnabled; bool mHWVsyncAvailable; + nsecs_t mRefreshStartTime; std::atomic mRefreshPending{false}; -- cgit v1.2.3-59-g8ed1b From 074e8122d54614a9e10fa09611fea0d1c3e3b95a Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Thu, 26 Jul 2018 12:57:23 -0700 Subject: Revert "Revert "surfacefligner: revert recent BE/FE split changes"" This reverts commit 0756cdd4b9cef33107ed13763d7168bc3363fae9. Reason for revert: b/111793219 Power regression, with urgent fix needed. Test: run cts -m CtsDeqpTestCases, run cts -m CtsViewTestCases Change-Id: I4f089100af6a788b5973961a214132c97597fa7e --- services/surfaceflinger/BufferLayer.cpp | 58 ++++- services/surfaceflinger/ColorLayer.cpp | 37 ++- services/surfaceflinger/Layer.cpp | 62 +++-- services/surfaceflinger/Layer.h | 8 - services/surfaceflinger/LayerBE.h | 6 +- services/surfaceflinger/SurfaceFlinger.cpp | 360 ++++++++--------------------- services/surfaceflinger/SurfaceFlinger.h | 26 +-- 7 files changed, 224 insertions(+), 333 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 75d8942f69..37f4b0f007 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -633,14 +633,37 @@ void BufferLayer::setPerFrameData(const sp& display) { const auto& viewport = display->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); const auto displayId = display->getId(); + if (!hasHwcLayer(displayId)) { + ALOGE("[%s] failed to setPerFrameData: no HWC layer found (%d)", + mName.string(), displayId); + return; + } + auto& hwcInfo = getBE().mHwcLayers[displayId]; + 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(error)); + visible.dump(LOG_TAG); + } - getBE().compositionInfo.hwc.visibleRegion = visible; - getBE().compositionInfo.hwc.surfaceDamage = surfaceDamageRegion; + 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(error)); + surfaceDamageRegion.dump(LOG_TAG); + } // Sideband layers if (getBE().compositionInfo.hwc.sidebandStream.get()) { setCompositionType(displayId, HWC2::Composition::Sideband); - getBE().compositionInfo.compositionType = HWC2::Composition::Sideband; + ALOGV("[%s] Requesting Sideband composition", mName.string()); + error = hwcLayer->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle()); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(), + getBE().compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(), + static_cast(error)); + } return; } @@ -653,14 +676,31 @@ void BufferLayer::setPerFrameData(const sp& display) { setCompositionType(displayId, HWC2::Composition::Device); } - getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace; - getBE().compositionInfo.hwc.hdrMetadata = mConsumer->getCurrentHdrMetadata(); - getBE().compositionInfo.hwc.supportedPerFrameMetadata = display->getSupportedPerFrameMetadata(); + ALOGV("setPerFrameData: dataspace = %d", mCurrentDataSpace); + error = hwcLayer->setDataspace(mCurrentDataSpace); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace, + to_string(error).c_str(), static_cast(error)); + } + + const HdrMetadata& metadata = mConsumer->getCurrentHdrMetadata(); + error = hwcLayer->setPerFrameMetadata(display->getSupportedPerFrameMetadata(), metadata); + if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) { + ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), + to_string(error).c_str(), static_cast(error)); + } + + uint32_t hwcSlot = 0; + sp hwcBuffer; + hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, &hwcSlot, &hwcBuffer); auto acquireFence = mConsumer->getCurrentFence(); - getBE().compositionInfo.mBufferSlot = mActiveBufferSlot; - getBE().compositionInfo.mBuffer = mActiveBuffer; - getBE().compositionInfo.hwc.fence = acquireFence; + error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), + getBE().compositionInfo.mBuffer->handle, to_string(error).c_str(), + static_cast(error)); + } } bool BufferLayer::isOpaque(const Layer::State& s) const { diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 884aedddb8..10075ae35f 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -76,18 +76,43 @@ void ColorLayer::setPerFrameData(const sp& display) { const auto& viewport = display->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); const auto displayId = display->getId(); - getBE().compositionInfo.hwc.visibleRegion = visible; - getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace; + if (!hasHwcLayer(displayId)) { + ALOGE("[%s] failed to setPerFrameData: no HWC layer found (%d)", + mName.string(), displayId); + return; + } + auto& hwcInfo = getBE().mHwcLayers[displayId]; + 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(error)); + visible.dump(LOG_TAG); + } setCompositionType(displayId, HWC2::Composition::SolidColor); + error = hwcLayer->setDataspace(mCurrentDataSpace); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace, + to_string(error).c_str(), static_cast(error)); + } + half4 color = getColor(); - getBE().compositionInfo.hwc.color = { static_cast(std::round(255.0f * color.r)), - static_cast(std::round(255.0f * color.g)), - static_cast(std::round(255.0f * color.b)), 255 }; + error = hwcLayer->setColor({static_cast(std::round(255.0f * color.r)), + static_cast(std::round(255.0f * color.g)), + static_cast(std::round(255.0f * color.b)), 255}); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set color: %s (%d)", mName.string(), to_string(error).c_str(), + static_cast(error)); + } // Clear out the transform, because it doesn't make sense absent a source buffer - getBE().compositionInfo.hwc.transform = HWC2::Transform::None; + 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(error)); + } } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 4eedb1a13d..40d89bdb10 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -503,9 +503,6 @@ void Layer::setGeometry(const sp& display, uint32_t z) { } auto& hwcInfo = getBE().mHwcLayers[displayId]; - // Need to program geometry parts - getBE().compositionInfo.hwc.skipGeometry = false; - // enable this layer hwcInfo.forceClientComposition = false; @@ -513,6 +510,8 @@ void Layer::setGeometry(const sp& display, uint32_t z) { hwcInfo.forceClientComposition = true; } + auto& hwcLayer = hwcInfo.layer; + // this gives us only the "orientation" component of the transform const State& s(getDrawingState()); auto blendMode = HWC2::BlendMode::None; @@ -520,7 +519,12 @@ void Layer::setGeometry(const sp& display, uint32_t z) { blendMode = mPremultipliedAlpha ? HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage; } - getBE().compositionInfo.hwc.blendMode = blendMode; + 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(error)); // apply the layer's transform, followed by the display's global transform // here we're guaranteed that the layer's transform preserves rects @@ -563,15 +567,36 @@ void Layer::setGeometry(const sp& display, uint32_t z) { } const Transform& tr = display->getTransform(); Rect transformedFrame = tr.transform(frame); - getBE().compositionInfo.hwc.displayFrame = transformedFrame; + 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(error)); + } else { + hwcInfo.displayFrame = transformedFrame; + } FloatRect sourceCrop = computeCrop(display); - getBE().compositionInfo.hwc.sourceCrop = sourceCrop; + 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(error)); + } else { + hwcInfo.sourceCrop = sourceCrop; + } float alpha = static_cast(getAlpha()); - getBE().compositionInfo.hwc.alpha = alpha; + 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(error)); - getBE().compositionInfo.hwc.z = z; + 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(error)); int type = s.type; int appId = s.appId; @@ -584,8 +609,9 @@ void Layer::setGeometry(const sp& display, uint32_t z) { } } - getBE().compositionInfo.hwc.type = type; - getBE().compositionInfo.hwc.appId = appId; + error = hwcLayer->setInfo(type, appId); + ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)", mName.string(), + static_cast(error)); /* * Transformations are applied in this order: @@ -622,11 +648,16 @@ void Layer::setGeometry(const sp& display, uint32_t z) { const uint32_t orientation = transform.getOrientation(); if (orientation & Transform::ROT_INVALID) { // we can only handle simple transformation - getBE().mHwcLayers[displayId].compositionType = HWC2::Composition::Client; + hwcInfo.forceClientComposition = true; } else { auto transform = static_cast(orientation); hwcInfo.transform = transform; - getBE().compositionInfo.hwc.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(error)); } } @@ -1467,16 +1498,17 @@ void Layer::miniDump(String8& result, int32_t displayId) const { result.appendFormat(" %s\n", name.string()); const Layer::State& layerState(getDrawingState()); + const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(displayId); if (layerState.zOrderRelativeOf != nullptr || mDrawingParent != nullptr) { result.appendFormat(" rel %6d | ", layerState.z); } else { result.appendFormat(" %10d | ", layerState.z); } result.appendFormat("%10s | ", to_string(getCompositionType(displayId)).c_str()); - result.appendFormat("%10s | ", to_string(getBE().mHwcLayers[displayId].transform).c_str()); - const Rect& frame = getBE().compositionInfo.hwc.displayFrame; + result.appendFormat("%10s | ", to_string(hwcInfo.transform).c_str()); + const Rect& frame = hwcInfo.displayFrame; result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom); - const FloatRect& crop = getBE().compositionInfo.hwc.sourceCrop; + 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.append("- - - - - - - - - - - - - - - -"); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 5107e6b32d..f72409652d 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -472,14 +472,6 @@ public: return getBE().mHwcLayers[displayId].layer; } - bool setHwcLayer(int32_t hwcId) { - if (getBE().mHwcLayers.count(hwcId) == 0) { - return false; - } - getBE().compositionInfo.hwc.hwcLayer = getBE().mHwcLayers[hwcId].layer; - return true; - } - // ----------------------------------------------------------------------- void clearWithOpenGL(const RenderArea& renderArea) const; diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 680fbd049c..9aa43f7fd3 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -19,9 +19,10 @@ #include #include -#include #include +#include "SurfaceFlinger.h" + #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/HWComposerBufferCache.h" #include "RenderEngine/Mesh.h" @@ -39,7 +40,6 @@ struct CompositionInfo { LayerBE* layer = nullptr; struct { HWC2::Layer* hwcLayer; - bool skipGeometry = true; sp fence; HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid; Rect displayFrame; @@ -54,8 +54,6 @@ struct CompositionInfo { sp sidebandStream; ui::Dataspace dataspace; hwc_color_t color; - bool supportedPerFrameMetadata = false; - HdrMetadata hdrMetadata; } hwc; struct { Mesh* mesh; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7da01c901e..ba5154d8e7 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -777,7 +777,6 @@ void SurfaceFlinger::init() { // set initial conditions (e.g. unblank default device) initializeDisplays(); - ALOGV("Displays initialized"); getBE().mRenderEngine->primeCache(); @@ -1544,13 +1543,7 @@ void SurfaceFlinger::onMessageReceived(int32_t what) { bool refreshNeeded = handleMessageTransaction(); refreshNeeded |= handleMessageInvalidate(); refreshNeeded |= mRepaintEverything; - - preComposition(); - rebuildLayerStacks(); - calculateWorkingSet(); - if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) { - // Signal a refresh if a transaction modified the window state, // a new buffer was latched, or if HWC has requested a full // repaint @@ -1579,112 +1572,21 @@ bool SurfaceFlinger::handleMessageInvalidate() { return handlePageFlip(); } -void SurfaceFlinger::calculateWorkingSet() { - ATRACE_CALL(); - ALOGV(__FUNCTION__); - - // build the h/w work list - if (CC_UNLIKELY(mGeometryInvalid)) { - mGeometryInvalid = false; - for (const auto& [token, display] : mDisplays) { - const auto displayId = display->getId(); - if (displayId >= 0) { - const Vector>& currentLayers( - display->getVisibleLayersSortedByZ()); - for (size_t i = 0; i < currentLayers.size(); i++) { - const auto& layer = currentLayers[i]; - - if (!layer->hasHwcLayer(displayId)) { - if (!layer->createHwcLayer(getBE().mHwc.get(), displayId)) { - layer->forceClientComposition(displayId); - continue; - } - } - - layer->setGeometry(display, i); - if (mDebugDisableHWC || mDebugRegion) { - layer->forceClientComposition(displayId); - } - } - } - } - } - - // Set the per-frame data - for (const auto& [token, display] : mDisplays) { - const auto displayId = display->getId(); - if (displayId < 0) { - continue; - } - - if (mDrawingState.colorMatrixChanged) { - display->setColorTransform(mDrawingState.colorMatrix); - status_t result = getBE().mHwc->setColorTransform(displayId, mDrawingState.colorMatrix); - ALOGE_IF(result != NO_ERROR, "Failed to set color transform on " - "display %d: %d", displayId, result); - } - for (auto& layer : display->getVisibleLayersSortedByZ()) { - if (layer->isHdrY410()) { - layer->forceClientComposition(displayId); - } else if ((layer->getDataSpace() == Dataspace::BT2020_PQ || - layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) && - !display->hasHDR10Support()) { - layer->forceClientComposition(displayId); - } else if ((layer->getDataSpace() == Dataspace::BT2020_HLG || - layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) && - !display->hasHLGSupport()) { - layer->forceClientComposition(displayId); - } - - if (layer->getForceClientComposition(displayId)) { - ALOGV("[%s] Requesting Client composition", layer->getName().string()); - layer->setCompositionType(displayId, HWC2::Composition::Client); - continue; - } - - layer->setPerFrameData(display); - } - - if (hasWideColorDisplay) { - ColorMode colorMode; - Dataspace dataSpace; - RenderIntent renderIntent; - pickColorMode(display, &colorMode, &dataSpace, &renderIntent); - setActiveColorModeInternal(display, colorMode, dataSpace, renderIntent); - } - } - - mDrawingState.colorMatrixChanged = false; - getBE().mCompositionInfo.clear(); - - for (const auto& [token, display] : mDisplays) { - for (auto& layer : display->getVisibleLayersSortedByZ()) { - auto displayId = display->getId(); - layer->getBE().compositionInfo.compositionType = layer->getCompositionType(displayId); - if (!layer->setHwcLayer(displayId)) { - ALOGV("Need to create HWCLayer for %s", layer->getName().string()); - } - getBE().mCompositionInfo.push_back(layer->getBE().compositionInfo); - layer->getBE().compositionInfo.hwc.hwcLayer = nullptr; - } - } -} - void SurfaceFlinger::handleMessageRefresh() { ATRACE_CALL(); mRefreshPending = false; - beginFrame(); - for (auto compositionInfo : getBE().mCompositionInfo) { - setUpHWComposer(compositionInfo); - } - prepareFrame(); + nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC); + + preComposition(refreshStartTime); + rebuildLayerStacks(); + setUpHWComposer(); doDebugFlashRegions(); doTracing("handleRefresh"); logLayerStats(); doComposition(); - postComposition(); + postComposition(refreshStartTime); mHadClientComposition = false; for (const auto& [token, display] : mDisplays) { @@ -1760,14 +1662,14 @@ void SurfaceFlinger::logLayerStats() { } } -void SurfaceFlinger::preComposition() +void SurfaceFlinger::preComposition(nsecs_t refreshStartTime) { ATRACE_CALL(); ALOGV("preComposition"); bool needExtraInvalidate = false; mDrawingState.traverseInZOrder([&](Layer* layer) { - if (layer->onPreComposition(mRefreshStartTime)) { + if (layer->onPreComposition(refreshStartTime)) { needExtraInvalidate = true; } }); @@ -1836,7 +1738,7 @@ void SurfaceFlinger::setCompositorTimingSnapped(nsecs_t vsyncPhase, getBE().mCompositorTiming.presentLatency = snappedCompositeToPresentLatency; } -void SurfaceFlinger::postComposition() +void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) { ATRACE_CALL(); ALOGV("postComposition"); @@ -1869,11 +1771,11 @@ void SurfaceFlinger::postComposition() nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0); nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod(); - // We use the mRefreshStartTime which might be sampled a little later than + // We use the refreshStartTime which might be sampled a little later than // when we started doing work for this frame, but that should be okay // since updateCompositorTiming has snapping logic. updateCompositorTiming( - vsyncPhase, vsyncInterval, mRefreshStartTime, presentFenceTime); + vsyncPhase, vsyncInterval, refreshStartTime, presentFenceTime); CompositorTiming compositorTiming; { std::lock_guard lock(getBE().mCompositorTimingLock); @@ -1985,21 +1887,15 @@ void SurfaceFlinger::rebuildLayerStacks() { if (!drawRegion.isEmpty()) { layersSortedByZ.add(layer); } else { - if (layer->hasHwcLayer(display->getId())) { - // Clear out the HWC layer if this layer was - // previously visible, but no longer is - hwcLayerDestroyed = layer->destroyHwcLayer( - display->getId()); - } + // Clear out the HWC layer if this layer was + // previously visible, but no longer is + hwcLayerDestroyed = layer->destroyHwcLayer(display->getId()); } } else { - if (layer->hasHwcLayer(display->getId())) { - // WM changes display->layerStack upon sleep/awake. - // Here we make sure we delete the HWC layers even if - // WM changed their layer stack. - hwcLayerDestroyed = layer->destroyHwcLayer( - display->getId()); - } + // WM changes display->layerStack upon sleep/awake. + // Here we make sure we delete the HWC layers even if + // WM changed their layer stack. + hwcLayerDestroyed = layer->destroyHwcLayer(display->getId()); } // If a layer is not going to get a release fence because @@ -2101,124 +1997,9 @@ void SurfaceFlinger::pickColorMode(const sp& display, ColorMode* display->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent); } -void SurfaceFlinger::configureSidebandComposition(const CompositionInfo& compositionInfo) const -{ - HWC2::Error error; - LOG_ALWAYS_FATAL_IF(compositionInfo.hwc.sidebandStream == nullptr, - "CompositionType is sideband, but sideband stream is nullptr"); - error = (compositionInfo.hwc.hwcLayer) - ->setSidebandStream(compositionInfo.hwc.sidebandStream->handle()); - if (error != HWC2::Error::None) { - ALOGE("[SF] Failed to set sideband stream %p: %s (%d)", - compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(), - static_cast(error)); - } -} - -void SurfaceFlinger::configureHwcCommonData(const CompositionInfo& compositionInfo) const -{ - HWC2::Error error; - - if (!compositionInfo.hwc.skipGeometry) { - error = (compositionInfo.hwc.hwcLayer)->setBlendMode(compositionInfo.hwc.blendMode); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set blend mode %s:" - " %s (%d)", - to_string(compositionInfo.hwc.blendMode).c_str(), to_string(error).c_str(), - static_cast(error)); - - error = (compositionInfo.hwc.hwcLayer)->setDisplayFrame(compositionInfo.hwc.displayFrame); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set the display frame [%d, %d, %d, %d] %s (%d)", - compositionInfo.hwc.displayFrame.left, - compositionInfo.hwc.displayFrame.right, - compositionInfo.hwc.displayFrame.top, - compositionInfo.hwc.displayFrame.bottom, - to_string(error).c_str(), static_cast(error)); - - error = (compositionInfo.hwc.hwcLayer)->setSourceCrop(compositionInfo.hwc.sourceCrop); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: %s (%d)", - compositionInfo.hwc.sourceCrop.left, - compositionInfo.hwc.sourceCrop.right, - compositionInfo.hwc.sourceCrop.top, - compositionInfo.hwc.sourceCrop.bottom, - to_string(error).c_str(), static_cast(error)); - - error = (compositionInfo.hwc.hwcLayer)->setPlaneAlpha(compositionInfo.hwc.alpha); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set plane alpha %.3f: " - "%s (%d)", - compositionInfo.hwc.alpha, - to_string(error).c_str(), static_cast(error)); - - - error = (compositionInfo.hwc.hwcLayer)->setZOrder(compositionInfo.hwc.z); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set Z %u: %s (%d)", - compositionInfo.hwc.z, - to_string(error).c_str(), static_cast(error)); - - error = (compositionInfo.hwc.hwcLayer) - ->setInfo(compositionInfo.hwc.type, compositionInfo.hwc.appId); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set info (%d)", - static_cast(error)); - - error = (compositionInfo.hwc.hwcLayer)->setTransform(compositionInfo.hwc.transform); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set transform %s: " - "%s (%d)", - to_string(compositionInfo.hwc.transform).c_str(), to_string(error).c_str(), - static_cast(error)); - } - - error = (compositionInfo.hwc.hwcLayer)->setCompositionType(compositionInfo.compositionType); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set composition type: %s (%d)", - to_string(error).c_str(), static_cast(error)); - - error = (compositionInfo.hwc.hwcLayer)->setDataspace(compositionInfo.hwc.dataspace); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set dataspace: %s (%d)", - to_string(error).c_str(), static_cast(error)); - - error = (compositionInfo.hwc.hwcLayer)->setPerFrameMetadata( - compositionInfo.hwc.supportedPerFrameMetadata, compositionInfo.hwc.hdrMetadata); - ALOGE_IF(error != HWC2::Error::None && error != HWC2::Error::Unsupported, - "[SF] Failed to set hdrMetadata: %s (%d)", - to_string(error).c_str(), static_cast(error)); - - error = (compositionInfo.hwc.hwcLayer)->setColor(compositionInfo.hwc.color); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set color: %s (%d)", - to_string(error).c_str(), static_cast(error)); - - error = (compositionInfo.hwc.hwcLayer)->setVisibleRegion(compositionInfo.hwc.visibleRegion); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set visible region: %s (%d)", - to_string(error).c_str(), static_cast(error)); -} - -void SurfaceFlinger::configureDeviceComposition(const CompositionInfo& compositionInfo) const -{ - HWC2::Error error; - - error = (compositionInfo.hwc.hwcLayer)->setSurfaceDamage(compositionInfo.hwc.surfaceDamage); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set surface damage: %s (%d)", - to_string(error).c_str(), static_cast(error)); - - error = (compositionInfo.hwc.hwcLayer)->setBuffer(compositionInfo.mBufferSlot, - compositionInfo.mBuffer, compositionInfo.hwc.fence); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set buffer: %s (%d)", - to_string(error).c_str(), static_cast(error)); -} - -void SurfaceFlinger::beginFrame() -{ - mRefreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC); +void SurfaceFlinger::setUpHWComposer() { + ATRACE_CALL(); + ALOGV("setUpHWComposer"); for (const auto& [token, display] : mDisplays) { bool dirty = !display->getDirtyRegion(mRepaintEverything).isEmpty(); @@ -2245,44 +2026,86 @@ void SurfaceFlinger::beginFrame() display->lastCompositionHadVisibleLayers = !empty; } } -} -void SurfaceFlinger::prepareFrame() -{ + // build the h/w work list + if (CC_UNLIKELY(mGeometryInvalid)) { + mGeometryInvalid = false; + for (const auto& [token, display] : mDisplays) { + const auto displayId = display->getId(); + if (displayId >= 0) { + const Vector>& currentLayers = display->getVisibleLayersSortedByZ(); + for (size_t i = 0; i < currentLayers.size(); i++) { + const auto& layer = currentLayers[i]; + if (!layer->hasHwcLayer(displayId)) { + if (!layer->createHwcLayer(getBE().mHwc.get(), displayId)) { + layer->forceClientComposition(displayId); + continue; + } + } + + layer->setGeometry(display, i); + if (mDebugDisableHWC || mDebugRegion) { + layer->forceClientComposition(displayId); + } + } + } + } + } + + // Set the per-frame data for (const auto& [token, display] : mDisplays) { - if (!display->isPoweredOn()) { + const auto displayId = display->getId(); + if (displayId < 0) { continue; } - status_t result = display->prepareFrame(*getBE().mHwc); - ALOGE_IF(result != NO_ERROR, "prepareFrame for display %d failed: %d (%s)", - display->getId(), result, strerror(-result)); - } -} + if (mDrawingState.colorMatrixChanged) { + display->setColorTransform(mDrawingState.colorMatrix); + status_t result = getBE().mHwc->setColorTransform(displayId, mDrawingState.colorMatrix); + ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display %d: %d", + displayId, result); + } + for (auto& layer : display->getVisibleLayersSortedByZ()) { + if (layer->isHdrY410()) { + layer->forceClientComposition(displayId); + } else if ((layer->getDataSpace() == Dataspace::BT2020_PQ || + layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) && + !display->hasHDR10Support()) { + layer->forceClientComposition(displayId); + } else if ((layer->getDataSpace() == Dataspace::BT2020_HLG || + layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) && + !display->hasHLGSupport()) { + layer->forceClientComposition(displayId); + } -void SurfaceFlinger::setUpHWComposer(const CompositionInfo& compositionInfo) { - ATRACE_CALL(); - ALOGV("setUpHWComposer"); + if (layer->getForceClientComposition(displayId)) { + ALOGV("[%s] Requesting Client composition", layer->getName().string()); + layer->setCompositionType(displayId, HWC2::Composition::Client); + continue; + } - switch (compositionInfo.compositionType) - { - case HWC2::Composition::Invalid: - case HWC2::Composition::Client: - break; + layer->setPerFrameData(display); + } - case HWC2::Composition::Sideband: - configureSidebandComposition(compositionInfo); - break; + if (hasWideColorDisplay) { + ColorMode colorMode; + Dataspace dataSpace; + RenderIntent renderIntent; + pickColorMode(display, &colorMode, &dataSpace, &renderIntent); + setActiveColorModeInternal(display, colorMode, dataSpace, renderIntent); + } + } - case HWC2::Composition::SolidColor: - configureHwcCommonData(compositionInfo); - break; + mDrawingState.colorMatrixChanged = false; - case HWC2::Composition::Device: - case HWC2::Composition::Cursor: - configureHwcCommonData(compositionInfo); - configureDeviceComposition(compositionInfo); - break; + for (const auto& [token, display] : mDisplays) { + if (!display->isPoweredOn()) { + continue; + } + + status_t result = display->prepareFrame(*getBE().mHwc); + ALOGE_IF(result != NO_ERROR, "prepareFrame for display %d failed: %d (%s)", + display->getId(), result, strerror(-result)); } } @@ -5445,6 +5268,7 @@ void SurfaceFlinger::traverseLayersInDisplay(const sp& disp }; // namespace android + #if defined(__gl_h_) #error "don't include gl/gl.h in this file" #endif diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 2978b7fe89..e107f425be 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -225,8 +225,6 @@ public: // use to differentiate callbacks from different hardware composer // instances. Each hardware composer instance gets a different sequence id. int32_t mComposerSequenceId; - - std::vector mCompositionInfo; }; @@ -645,8 +643,8 @@ private: void computeVisibleRegions(const sp& display, Region& dirtyRegion, Region& opaqueRegion); - void preComposition(); - void postComposition(); + void preComposition(nsecs_t refreshStartTime); + void postComposition(nsecs_t refreshStartTime); void updateCompositorTiming( nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime, std::shared_ptr& presentFenceTime); @@ -664,19 +662,7 @@ private: void pickColorMode(const sp& display, ui::ColorMode* outMode, ui::Dataspace* outDataSpace, ui::RenderIntent* outRenderIntent) const; - void calculateWorkingSet(); - /* - * beginFrame - This function handles any pre-frame processing that needs to be - * prior to any CompositionInfo handling and is not dependent on data in - * CompositionInfo - */ - void beginFrame(); - /* prepareFrame - This function will call into the DisplayDevice to prepare a - * frame after CompositionInfo has been programmed. This provides a mechanism - * to prepare the hardware composer - */ - void prepareFrame(); - void setUpHWComposer(const CompositionInfo& compositionInfo); + void setUpHWComposer(); void doComposition(); void doDebugFlashRegions(); void doTracing(const char* where); @@ -794,11 +780,6 @@ private: // access must be protected by mInvalidateLock volatile int32_t mRepaintEverything; - // helper methods - void configureHwcCommonData(const CompositionInfo& compositionInfo) const; - void configureDeviceComposition(const CompositionInfo& compositionInfo) const; - void configureSidebandComposition(const CompositionInfo& compositionInfo) const; - // constant members (no synchronization needed for access) nsecs_t mBootTime; bool mGpuToCpuSupported; @@ -877,7 +858,6 @@ private: Mutex mHWVsyncLock; bool mPrimaryHWVsyncEnabled; bool mHWVsyncAvailable; - nsecs_t mRefreshStartTime; std::atomic mRefreshPending{false}; -- cgit v1.2.3-59-g8ed1b From fd668629dfc5771b2c6ce8b14162f7ce8b6618ce Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 10 May 2018 10:21:13 -0700 Subject: blast: Factor out BufferQueueLayer Remove all BufferQueue related items from BufferLayer and Layer into a new BufferQueueLayer class. Bug: 80477568 Test: Transaction_test.cpp Change-Id: I7fcc49768e2723b4991d4566c5124451e328bdf0 --- services/surfaceflinger/Android.bp | 1 + services/surfaceflinger/BufferLayer.cpp | 648 +++++++-------------------- services/surfaceflinger/BufferLayer.h | 173 ++++--- services/surfaceflinger/BufferQueueLayer.cpp | 482 ++++++++++++++++++++ services/surfaceflinger/BufferQueueLayer.h | 144 ++++++ services/surfaceflinger/Layer.cpp | 9 - services/surfaceflinger/Layer.h | 22 +- services/surfaceflinger/LayerBE.h | 1 + services/surfaceflinger/SurfaceFlinger.cpp | 23 +- services/surfaceflinger/SurfaceFlinger.h | 9 +- 10 files changed, 892 insertions(+), 620 deletions(-) create mode 100644 services/surfaceflinger/BufferQueueLayer.cpp create mode 100644 services/surfaceflinger/BufferQueueLayer.h (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index b91971027b..0be1fd7d93 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -91,6 +91,7 @@ filegroup { srcs: [ "BufferLayer.cpp", "BufferLayerConsumer.cpp", + "BufferQueueLayer.cpp", "Client.cpp", "ColorLayer.cpp", "ContainerLayer.cpp", diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 37f4b0f007..7246c8e890 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -53,22 +53,18 @@ namespace android { BufferLayer::BufferLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags) : Layer(flinger, client, name, w, h, flags), - mConsumer(nullptr), - mTextureName(UINT32_MAX), - mFormat(PIXEL_FORMAT_NONE), + mTextureName(mFlinger->getNewTexture()), mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), mBufferLatched(false), - mPreviousFrameNumber(0), - mUpdateTexImageFailed(false), mRefreshPending(false) { ALOGV("Creating Layer %s", name.string()); - mTextureName = mFlinger->getNewTexture(); mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName); - if (flags & ISurfaceComposerClient::eNonPremultiplied) mPremultipliedAlpha = false; + mPremultipliedAlpha = !(flags & ISurfaceComposerClient::eNonPremultiplied); - mCurrentState.requested = mCurrentState.active; + mPotentialCursor = flags & ISurfaceComposerClient::eCursorWindow; + mProtectedByApp = flags & ISurfaceComposerClient::eProtectedByApp; // drawing state & current state are identical mDrawingState = mCurrentState; @@ -89,7 +85,7 @@ void BufferLayer::useSurfaceDamage() { if (mFlinger->mForceFullDamage) { surfaceDamageRegion = Region::INVALID_REGION; } else { - surfaceDamageRegion = mConsumer->getSurfaceDamage(); + surfaceDamageRegion = getDrawingSurfaceDamage(); } } @@ -97,9 +93,16 @@ void BufferLayer::useEmptyDamage() { surfaceDamageRegion.clear(); } -bool BufferLayer::isProtected() const { - const sp& buffer(mActiveBuffer); - return (buffer != 0) && (buffer->getUsage() & GRALLOC_USAGE_PROTECTED); +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 ((getBE().compositionInfo.hwc.sidebandStream == 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) || getOpacityForFormat(getPixelFormat()); } bool BufferLayer::isVisible() const { @@ -111,30 +114,6 @@ 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); - - mConsumer->setDefaultBufferSize(w, h); - mConsumer->setDefaultBufferFormat(format); - mConsumer->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); @@ -191,7 +170,7 @@ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, // Bind the current buffer to the GL texture, and wait for it to be // ready for us to draw into. - status_t err = mConsumer->bindTextureImage(); + status_t err = 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 @@ -208,8 +187,8 @@ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, // Query the texture matrix given our current filtering mode. float textureMatrix[16]; - mConsumer->setFilteringEnabled(useFiltering); - mConsumer->getTransformMatrix(textureMatrix); + setFilteringEnabled(useFiltering); + getDrawingTransformMatrix(textureMatrix); if (getTransformToDisplayInverse()) { /* @@ -270,39 +249,78 @@ void BufferLayer::drawNow(const RenderArea& renderArea, bool useIdentityTransfor engine.setSourceY410BT2020(false); } -void BufferLayer::onLayerDisplayed(const sp& releaseFence) { - mConsumer->setReleaseFence(releaseFence); +bool BufferLayer::isHdrY410() const { + // pixel format is HDR Y410 masquerading as RGBA_1010102 + return (mCurrentDataSpace == ui::Dataspace::BT2020_ITU_PQ && + getDrawingApi() == NATIVE_WINDOW_API_MEDIA && + getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102); } -void BufferLayer::abandon() { - mConsumer->abandon(); -} +void BufferLayer::setPerFrameData(const sp& display) { + // Apply this display's projection's viewport to the visible region + // before giving it to the HWC HAL. + const Transform& tr = display->getTransform(); + const auto& viewport = display->getViewport(); + Region visible = tr.transform(visibleRegion.intersect(viewport)); + const auto displayId = display->getId(); + if (!hasHwcLayer(displayId)) { + ALOGE("[%s] failed to setPerFrameData: no HWC layer found (%d)", + mName.string(), displayId); + return; + } + auto& hwcInfo = getBE().mHwcLayers[displayId]; + 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(error)); + visible.dump(LOG_TAG); + } -bool BufferLayer::shouldPresentNow(const DispSync& dispSync) const { - if (mSidebandStreamChanged || mAutoRefresh) { - return true; + 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(error)); + surfaceDamageRegion.dump(LOG_TAG); } - Mutex::Autolock lock(mQueueItemLock); - if (mQueueItems.empty()) { - return false; + // Sideband layers + if (getBE().compositionInfo.hwc.sidebandStream.get()) { + setCompositionType(displayId, HWC2::Composition::Sideband); + ALOGV("[%s] Requesting Sideband composition", mName.string()); + error = hwcLayer->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle()); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(), + getBE().compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(), + static_cast(error)); + } + return; } - auto timestamp = mQueueItems[0].mTimestamp; - nsecs_t expectedPresent = mConsumer->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); + // Device or Cursor layers + if (mPotentialCursor) { + ALOGV("[%s] Requesting Cursor composition", mName.string()); + setCompositionType(displayId, HWC2::Composition::Cursor); + } else { + ALOGV("[%s] Requesting Device composition", mName.string()); + setCompositionType(displayId, HWC2::Composition::Device); + } - bool isDue = timestamp < expectedPresent; - return isDue || !isPlausible; -} + ALOGV("setPerFrameData: dataspace = %d", mCurrentDataSpace); + error = hwcLayer->setDataspace(mCurrentDataSpace); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace, + to_string(error).c_str(), static_cast(error)); + } + + const HdrMetadata& metadata = getDrawingHdrMetadata(); + error = hwcLayer->setPerFrameMetadata(display->getSupportedPerFrameMetadata(), metadata); + if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) { + ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), + to_string(error).c_str(), static_cast(error)); + } -void BufferLayer::setTransformHint(uint32_t orientation) const { - mConsumer->setTransformHint(orientation); + setHwcLayerBuffer(display); } bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { @@ -311,8 +329,9 @@ bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime); } mRefreshPending = false; - return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh; + return hasReadyFrame(); } + bool BufferLayer::onPostComposition(const std::shared_ptr& glDoneFence, const std::shared_ptr& presentFence, const CompositorTiming& compositorTiming) { @@ -328,13 +347,13 @@ bool BufferLayer::onPostComposition(const std::shared_ptr& glDoneFenc } // Update mFrameTracker. - nsecs_t desiredPresentTime = mConsumer->getTimestamp(); + nsecs_t desiredPresentTime = getDesiredPresentTime(); mFrameTracker.setDesiredPresentTime(desiredPresentTime); const std::string layerName(getName().c_str()); mTimeStats.setDesiredTime(layerName, mCurrentFrameNumber, desiredPresentTime); - std::shared_ptr frameReadyFence = mConsumer->getCurrentFenceTime(); + std::shared_ptr frameReadyFence = getCurrentFenceTime(); if (frameReadyFence->isValid()) { mFrameTracker.setFrameReadyFence(std::move(frameReadyFence)); } else { @@ -360,57 +379,19 @@ bool BufferLayer::onPostComposition(const std::shared_ptr& glDoneFenc return true; } -std::vector BufferLayer::getOccupancyHistory(bool forceFlush) { - std::vector history; - status_t result = mConsumer->getOccupancyHistory(forceFlush, &history); - if (result != NO_ERROR) { - ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(), result); - return {}; - } - return history; -} - -bool BufferLayer::getTransformToDisplayInverse() const { - return mConsumer->getTransformToDisplayInverse(); -} - -void BufferLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { - if (!mConsumer->releasePendingBuffer()) { - return; - } - - auto releaseFenceTime = std::make_shared(mConsumer->getPrevFinalReleaseFence()); - mReleaseTimeline.updateSignalTimes(); - mReleaseTimeline.push(releaseFenceTime); - - Mutex::Autolock lock(mFrameEventHistoryMutex); - if (mPreviousFrameNumber != 0) { - mFrameEventHistory.addRelease(mPreviousFrameNumber, dequeueReadyTime, - std::move(releaseFenceTime)); - } -} - Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) { ATRACE_CALL(); - if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) { - // mSidebandStreamChanged was true - mSidebandStream = mConsumer->getSidebandStream(); - // replicated in LayerBE until FE/BE is ready to be synchronized - getBE().compositionInfo.hwc.sidebandStream = mSidebandStream; - if (getBE().compositionInfo.hwc.sidebandStream != nullptr) { - setTransactionFlags(eTransactionNeeded); - mFlinger->setTransactionFlags(eTraversalNeeded); - } - recomputeVisibleRegions = true; + std::optional sidebandStreamDirtyRegion = latchSidebandStream(recomputeVisibleRegions); - const State& s(getDrawingState()); - return getTransform().transform(Region(Rect(s.active.w, s.active.h))); + if (sidebandStreamDirtyRegion) { + return *sidebandStreamDirtyRegion; } - Region outDirtyRegion; - if (mQueuedFrames <= 0 && !mAutoRefresh) { - return outDirtyRegion; + Region dirtyRegion; + + if (!hasReadyFrame()) { + return dirtyRegion; } // if we've already called updateTexImage() without going through @@ -419,14 +400,14 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime // compositionComplete() call. // we'll trigger an update in onPreComposition(). if (mRefreshPending) { - return outDirtyRegion; + return dirtyRegion; } // If the head buffer's acquire fence hasn't signaled yet, return and // try again later - if (!headFenceHasSignaled()) { + if (!fenceHasSignaled()) { mFlinger->signalLayerUpdate(); - return outDirtyRegion; + return dirtyRegion; } // Capture the old state of the layer for comparisons later @@ -436,101 +417,24 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime 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, - getTransformToDisplayInverse(), mFreezeGeometryUpdates); - - status_t updateResult = mConsumer->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 == BufferLayerConsumer::BUFFER_REJECTED) { - // If the buffer has been rejected, remove it from the shadow queue - // and return early - if (queuedBuffer) { - Mutex::Autolock lock(mQueueItemLock); - mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber); - 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); - mTimeStats.clearLayerRecord(getName().c_str()); - } - - // 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; + return dirtyRegion; } - if (queuedBuffer) { - // Autolock scope - auto currentFrameNumber = mConsumer->getFrameNumber(); - - Mutex::Autolock lock(mQueueItemLock); - - // Remove any stale buffers that have been dropped during - // updateTexImage - while (mQueueItems[0].mFrameNumber != currentFrameNumber) { - mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber); - mQueueItems.removeAt(0); - android_atomic_dec(&mQueuedFrames); - } - - const std::string layerName(getName().c_str()); - mTimeStats.setAcquireFence(layerName, currentFrameNumber, mQueueItems[0].mFenceTime); - mTimeStats.setLatchTime(layerName, currentFrameNumber, latchTime); - - 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(); + status_t err = updateTexImage(recomputeVisibleRegions, latchTime); + if (err != NO_ERROR) { + return dirtyRegion; } - // update the active buffer - mActiveBuffer = mConsumer->getCurrentBuffer(&mActiveBufferSlot); - getBE().compositionInfo.mBuffer = mActiveBuffer; - getBE().compositionInfo.mBufferSlot = mActiveBufferSlot; - - if (mActiveBuffer == nullptr) { - // this can only happen if the very first buffer was rejected. - return outDirtyRegion; + err = updateActiveBuffer(); + if (err != NO_ERROR) { + return dirtyRegion; } mBufferLatched = true; - mPreviousFrameNumber = mCurrentFrameNumber; - mCurrentFrameNumber = mConsumer->getFrameNumber(); - { - Mutex::Autolock lock(mFrameEventHistoryMutex); - mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime); + err = updateFrameNumber(latchTime); + if (err != NO_ERROR) { + return dirtyRegion; } mRefreshPending = true; @@ -541,7 +445,7 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime recomputeVisibleRegions = true; } - ui::Dataspace dataSpace = mConsumer->getCurrentDataSpace(); + ui::Dataspace dataSpace = getDrawingDataSpace(); // treat modern dataspaces as legacy dataspaces whenever possible, until // we can trust the buffer producers switch (dataSpace) { @@ -568,9 +472,9 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime } mCurrentDataSpace = dataSpace; - Rect crop(mConsumer->getCurrentCrop()); - const uint32_t transform(mConsumer->getCurrentTransform()); - const uint32_t scalingMode(mConsumer->getCurrentScalingMode()); + Rect crop(getDrawingCrop()); + const uint32_t transform(getDrawingTransform()); + const uint32_t scalingMode(getDrawingScalingMode()); if ((crop != mCurrentCrop) || (transform != mCurrentTransform) || (scalingMode != mCurrentScalingMode)) { mCurrentCrop = crop; @@ -587,7 +491,6 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime } } - mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format); if (oldOpacity != isOpaque(s)) { recomputeVisibleRegions = true; } @@ -614,201 +517,78 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime } // 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; + return getTransform().transform(Region(Rect(s.active.w, s.active.h))); } -void BufferLayer::setDefaultBufferSize(uint32_t w, uint32_t h) { - mConsumer->setDefaultBufferSize(w, h); -} - -void BufferLayer::setPerFrameData(const sp& display) { - // Apply this display's projection's viewport to the visible region - // before giving it to the HWC HAL. - const Transform& tr = display->getTransform(); - const auto& viewport = display->getViewport(); - Region visible = tr.transform(visibleRegion.intersect(viewport)); - const auto displayId = display->getId(); - if (!hasHwcLayer(displayId)) { - ALOGE("[%s] failed to setPerFrameData: no HWC layer found (%d)", - mName.string(), displayId); - return; - } - auto& hwcInfo = getBE().mHwcLayers[displayId]; - 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(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(error)); - surfaceDamageRegion.dump(LOG_TAG); - } - - // Sideband layers - if (getBE().compositionInfo.hwc.sidebandStream.get()) { - setCompositionType(displayId, HWC2::Composition::Sideband); - ALOGV("[%s] Requesting Sideband composition", mName.string()); - error = hwcLayer->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle()); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(), - getBE().compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(), - static_cast(error)); +// transaction +void BufferLayer::notifyAvailableFrames() { + auto headFrameNumber = getHeadFrameNumber(); + bool headFenceSignaled = fenceHasSignaled(); + Mutex::Autolock lock(mLocalSyncPointMutex); + for (auto& point : mLocalSyncPoints) { + if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled) { + point->setFrameAvailable(); } - return; - } - - // Device or Cursor layers - if (mPotentialCursor) { - ALOGV("[%s] Requesting Cursor composition", mName.string()); - setCompositionType(displayId, HWC2::Composition::Cursor); - } else { - ALOGV("[%s] Requesting Device composition", mName.string()); - setCompositionType(displayId, HWC2::Composition::Device); - } - - ALOGV("setPerFrameData: dataspace = %d", mCurrentDataSpace); - error = hwcLayer->setDataspace(mCurrentDataSpace); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace, - to_string(error).c_str(), static_cast(error)); - } - - const HdrMetadata& metadata = mConsumer->getCurrentHdrMetadata(); - error = hwcLayer->setPerFrameMetadata(display->getSupportedPerFrameMetadata(), metadata); - if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) { - ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast(error)); - } - - uint32_t hwcSlot = 0; - sp hwcBuffer; - hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, &hwcSlot, &hwcBuffer); - - auto acquireFence = mConsumer->getCurrentFence(); - error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), - getBE().compositionInfo.mBuffer->handle, to_string(error).c_str(), - static_cast(error)); } } -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 ((getBE().compositionInfo.hwc.sidebandStream == 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 BufferLayer::hasReadyFrame() const { + return hasDrawingBuffer() || getSidebandStreamChanged() || getAutoRefresh(); } -void BufferLayer::onFirstRef() { - // Creates a custom BufferQueue for SurfaceFlingerConsumer to use - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer, true); - mProducer = new MonitoredProducer(producer, mFlinger, this); - { - // Grab the SF state lock during this since it's the only safe way to access RenderEngine - Mutex::Autolock lock(mFlinger->mStateLock); - mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, - this); - } - mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); - mConsumer->setContentsChangedListener(this); - mConsumer->setName(mName); - - if (mFlinger->isLayerTripleBufferingDisabled()) { - mProducer->setMaxDequeuedBufferCount(2); +uint32_t BufferLayer::getEffectiveScalingMode() const { + if (mOverrideScalingMode >= 0) { + return mOverrideScalingMode; } - if (const auto display = mFlinger->getDefaultDisplayDevice()) { - updateTransformHint(display); - } + return mCurrentScalingMode; } -// --------------------------------------------------------------------------- -// 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); +bool BufferLayer::isProtected() const { + const sp& buffer(mActiveBuffer); + return (buffer != 0) && (buffer->getUsage() & GRALLOC_USAGE_PROTECTED); +} - // Wake up any pending callbacks - mLastFrameNumberReceived = item.mFrameNumber; - mQueueItemCondition.broadcast(); +bool BufferLayer::latchUnsignaledBuffers() { + static bool propertyLoaded = false; + static bool latch = false; + static std::mutex mutex; + std::lock_guard lock(mutex); + if (!propertyLoaded) { + char value[PROPERTY_VALUE_MAX] = {}; + property_get("debug.sf.latch_unsignaled", value, "0"); + latch = atoi(value); + propertyLoaded = true; } - - mFlinger->signalLayerUpdate(); + return latch; } -void BufferLayer::onFrameReplaced(const BufferItem& item) { - { // Autolock scope - Mutex::Autolock lock(mQueueItemLock); +// h/w composer set-up +bool BufferLayer::allTransactionsSignaled() { + auto headFrameNumber = getHeadFrameNumber(); + bool matchingFramesFound = false; + bool allTransactionsApplied = true; + Mutex::Autolock lock(mLocalSyncPointMutex); - // 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()); - } + for (auto& point : mLocalSyncPoints) { + if (point->getFrameNumber() > headFrameNumber) { + break; } + matchingFramesFound = true; - if (mQueueItems.empty()) { - ALOGE("Can't replace a frame on an empty queue"); - return; + 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; } - 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(); + allTransactionsApplied = allTransactionsApplied && point->transactionIsApplied(); } -} - -bool BufferLayer::needsFiltering(const RenderArea& renderArea) const { - return mNeedsFiltering || renderArea.needsFiltering(); + return !matchingFramesFound || allTransactionsApplied; } // As documented in libhardware header, formats in the range @@ -833,11 +613,8 @@ bool BufferLayer::getOpacityForFormat(uint32_t format) { return true; } -bool BufferLayer::isHdrY410() const { - // pixel format is HDR Y410 masquerading as RGBA_1010102 - return (mCurrentDataSpace == ui::Dataspace::BT2020_ITU_PQ && - mConsumer->getCurrentApi() == NATIVE_WINDOW_API_MEDIA && - getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102); +bool BufferLayer::needsFiltering(const RenderArea& renderArea) const { + return mNeedsFiltering || renderArea.needsFiltering(); } void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const { @@ -903,115 +680,14 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT engine.setSourceY410BT2020(false); } -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(producerStickyTransform); -} - -bool BufferLayer::latchUnsignaledBuffers() { - static bool propertyLoaded = false; - static bool latch = false; - static std::mutex mutex; - std::lock_guard 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; + if (hasDrawingBuffer()) { + return getFrameNumber(); } else { return mCurrentFrameNumber; } } -bool BufferLayer::headFenceHasSignaled() const { - 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; -} - -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 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_) diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 0886f17e91..6ffcff4a2a 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -47,152 +47,143 @@ namespace android { -/* - * A new BufferQueue and a new BufferLayerConsumer 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 BufferLayerConsumer::ContentsChangedListener { +class BufferLayer : public Layer { public: BufferLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags); ~BufferLayer() override; - // If we have received a new buffer this frame, we will pass its surface - // damage down to hardware composer. Otherwise, we must send a region with - // one empty rect. - void useSurfaceDamage(); - void useEmptyDamage(); - // ----------------------------------------------------------------------- // Overriden from Layer // ----------------------------------------------------------------------- +public: + // If we have received a new buffer this frame, we will pass its surface + // damage down to hardware composer. Otherwise, we must send a region with + // one empty rect. + void useSurfaceDamage() override; + void useEmptyDamage() override; - /* - * getTypeId - Provide unique string for each class type in the Layer - * hierarchy - */ + // 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; + bool isOpaque(const Layer::State& s) const override; - /* - * isVisible - true if this layer is visible, false otherwise - */ + // isVisible - true if this layer is visible, false otherwise bool isVisible() const override; - /* - * isFixedSize - true if content has a fixed size - */ + // 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. - */ + // onDraw - draws the surface. void onDraw(const RenderArea& renderArea, const Region& clip, bool useIdentityTransform) const override; void drawNow(const RenderArea& renderArea, bool useIdentityTransform) const; - void onLayerDisplayed(const sp& releaseFence) override; + bool isHdrY410() const override; + + void setPerFrameData(const sp& displayDevice) override; - void abandon() override; - bool shouldPresentNow(const DispSync& dispSync) const override; - void setTransformHint(uint32_t orientation) const override; + bool onPreComposition(nsecs_t refreshStartTime) override; bool onPostComposition(const std::shared_ptr& glDoneFence, const std::shared_ptr& presentFence, const CompositorTiming& compositorTiming) override; - std::vector getOccupancyHistory(bool forceFlush) override; - bool getTransformToDisplayInverse() const override; -public: - bool onPreComposition(nsecs_t refreshStartTime) override; - - // If a buffer was replaced this frame, release the former buffer - void releasePendingBuffer(nsecs_t dequeueReadyTime); - - /* - * 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. - */ + // 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; } - void setDefaultBufferSize(uint32_t w, uint32_t h) override; - bool isHdrY410() const override; + void notifyAvailableFrames() override; - void setPerFrameData(const sp& display) override; + bool hasReadyFrame() const override; - bool isOpaque(const Layer::State& s) const override; +private: + // Returns the current scaling mode, unless mOverrideScalingMode + // is set, in which case, it returns mOverrideScalingMode + uint32_t getEffectiveScalingMode() const override; + // ----------------------------------------------------------------------- + // ----------------------------------------------------------------------- + // Functions that must be implemented by derived classes + // ----------------------------------------------------------------------- private: - void onFirstRef() override; + virtual bool fenceHasSignaled() const = 0; - // Interface implementation for - // BufferLayerConsumer::ContentsChangedListener - void onFrameAvailable(const BufferItem& item) override; - void onFrameReplaced(const BufferItem& item) override; - void onSidebandStreamChanged() override; + virtual nsecs_t getDesiredPresentTime() = 0; + virtual std::shared_ptr getCurrentFenceTime() const = 0; - // needsLinearFiltering - true if this surface's state requires filtering - bool needsFiltering(const RenderArea& renderArea) const; + virtual void getDrawingTransformMatrix(float matrix[16]) const = 0; + virtual uint32_t getDrawingTransform() const = 0; + virtual ui::Dataspace getDrawingDataSpace() const = 0; + virtual Rect getDrawingCrop() const = 0; + virtual uint32_t getDrawingScalingMode() const = 0; + virtual Region getDrawingSurfaceDamage() const = 0; + virtual const HdrMetadata& getDrawingHdrMetadata() const = 0; + virtual int getDrawingApi() const = 0; + virtual PixelFormat getPixelFormat() const = 0; - static bool getOpacityForFormat(uint32_t format); + virtual uint64_t getFrameNumber() const = 0; - // drawing - void drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const; + virtual bool getAutoRefresh() const = 0; + virtual bool getSidebandStreamChanged() const = 0; - // Temporary - Used only for LEGACY camera mode. - uint32_t getProducerStickyTransform() const; + virtual std::optional latchSidebandStream(bool& recomputeVisibleRegions) = 0; - // Loads the corresponding system property once per process - static bool latchUnsignaledBuffers(); + virtual bool hasDrawingBuffer() const = 0; - uint64_t getHeadFrameNumber() const; - bool headFenceHasSignaled() const; + virtual void setFilteringEnabled(bool enabled) const = 0; - // Returns the current scaling mode, unless mOverrideScalingMode - // is set, in which case, it returns mOverrideScalingMode - uint32_t getEffectiveScalingMode() const override; + virtual status_t bindTextureImage() const = 0; + virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) = 0; -public: - void notifyAvailableFrames() override; + virtual status_t updateActiveBuffer() = 0; + virtual status_t updateFrameNumber(nsecs_t latchTime) = 0; - PixelFormat getPixelFormat() const override { return mFormat; } - sp getProducer() const; + virtual void setHwcLayerBuffer(const sp& display) = 0; -private: - sp mConsumer; + // ----------------------------------------------------------------------- + +public: + // isProtected - true if the layer may contain protected content in the + // GRALLOC_USAGE_PROTECTED sense. + bool isProtected() const; + +protected: + // Loads the corresponding system property once per process + static bool latchUnsignaledBuffers(); // 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 mProducer; - // constants - uint32_t mTextureName; // from GLES - PixelFormat mFormat; + static bool getOpacityForFormat(uint32_t format); + + // from GLES + const uint32_t mTextureName; + +private: + // needsLinearFiltering - true if this surface's state requires filtering + bool needsFiltering(const RenderArea& renderArea) const; + + // drawing + void drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const; + + uint64_t getHeadFrameNumber() const; - // main thread uint32_t mCurrentScalingMode; - bool mBufferLatched = false; // TODO: Use mActiveBuffer? - uint64_t mPreviousFrameNumber; // Only accessed on the main thread. + + // main thread. + bool mBufferLatched; // TODO: Use mActiveBuffer? + // 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; }; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp new file mode 100644 index 0000000000..d5a94b7c6a --- /dev/null +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -0,0 +1,482 @@ +/* + * Copyright (C) 2018 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. + */ + +#include "BufferQueueLayer.h" +#include "LayerRejecter.h" +#include "clz.h" + +#include + +namespace android { + +BufferQueueLayer::BufferQueueLayer(SurfaceFlinger* flinger, const sp& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags) + : BufferLayer(flinger, client, name, w, h, flags), + mConsumer(nullptr), + mProducer(nullptr), + mFormat(PIXEL_FORMAT_NONE), + mPreviousFrameNumber(0), + mUpdateTexImageFailed(false), + mQueueItemLock(), + mQueueItemCondition(), + mQueueItems(), + mLastFrameNumberReceived(0), + mAutoRefresh(false), + mActiveBufferSlot(BufferQueue::INVALID_BUFFER_SLOT), + mQueuedFrames(0), + mSidebandStreamChanged(false) { + mCurrentState.requested = mCurrentState.active; +} + +// ----------------------------------------------------------------------- +// Interface implementation for Layer +// ----------------------------------------------------------------------- + +void BufferQueueLayer::onLayerDisplayed(const sp& releaseFence) { + mConsumer->setReleaseFence(releaseFence); +} + +void BufferQueueLayer::abandon() { + mConsumer->abandon(); +} + +void BufferQueueLayer::setTransformHint(uint32_t orientation) const { + mConsumer->setTransformHint(orientation); +} + +std::vector BufferQueueLayer::getOccupancyHistory(bool forceFlush) { + std::vector history; + status_t result = mConsumer->getOccupancyHistory(forceFlush, &history); + if (result != NO_ERROR) { + ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(), result); + return {}; + } + return history; +} + +bool BufferQueueLayer::getTransformToDisplayInverse() const { + return mConsumer->getTransformToDisplayInverse(); +} + +void BufferQueueLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { + if (!mConsumer->releasePendingBuffer()) { + return; + } + + auto releaseFenceTime = std::make_shared(mConsumer->getPrevFinalReleaseFence()); + mReleaseTimeline.updateSignalTimes(); + mReleaseTimeline.push(releaseFenceTime); + + Mutex::Autolock lock(mFrameEventHistoryMutex); + if (mPreviousFrameNumber != 0) { + mFrameEventHistory.addRelease(mPreviousFrameNumber, dequeueReadyTime, + std::move(releaseFenceTime)); + } +} + +void BufferQueueLayer::setDefaultBufferSize(uint32_t w, uint32_t h) { + mConsumer->setDefaultBufferSize(w, h); +} + +int32_t BufferQueueLayer::getQueuedFrameCount() const { + return mQueuedFrames; +} + +bool BufferQueueLayer::shouldPresentNow(const DispSync& dispSync) const { + if (getSidebandStreamChanged() || getAutoRefresh()) { + return true; + } + + if (!hasDrawingBuffer()) { + return false; + } + + Mutex::Autolock lock(mQueueItemLock); + + const int64_t addedTime = mQueueItems[0].mTimestamp; + const nsecs_t expectedPresentTime = mConsumer->computeExpectedPresent(dispSync); + + // Ignore timestamps more than a second in the future + const bool isPlausible = addedTime < (expectedPresentTime + s2ns(1)); + ALOGW_IF(!isPlausible, + "[%s] Timestamp %" PRId64 " seems implausible " + "relative to expectedPresent %" PRId64, + mName.string(), addedTime, expectedPresentTime); + + const bool isDue = addedTime < expectedPresentTime; + return isDue || !isPlausible; +} + +// ----------------------------------------------------------------------- +// Interface implementation for BufferLayer +// ----------------------------------------------------------------------- + +bool BufferQueueLayer::fenceHasSignaled() const { + if (latchUnsignaledBuffers()) { + return true; + } + + if (!hasDrawingBuffer()) { + return true; + } + + Mutex::Autolock lock(mQueueItemLock); + 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; +} + +nsecs_t BufferQueueLayer::getDesiredPresentTime() { + return mConsumer->getTimestamp(); +} + +std::shared_ptr BufferQueueLayer::getCurrentFenceTime() const { + return mConsumer->getCurrentFenceTime(); +} + +void BufferQueueLayer::getDrawingTransformMatrix(float matrix[16]) const { + return mConsumer->getTransformMatrix(matrix); +} + +// NOTE: SurfaceFlinger's definitions of "Current" and "Drawing" do not neatly map to BufferQueue's +// These functions get the fields for the frame that is currently in SurfaceFlinger's Drawing state +// so the functions start with "getDrawing". The data is retrieved from the BufferQueueConsumer's +// current buffer so the consumer functions start with "getCurrent". +// +// This results in the rather confusing functions below. +uint32_t BufferQueueLayer::getDrawingTransform() const { + return mConsumer->getCurrentTransform(); +} + +ui::Dataspace BufferQueueLayer::getDrawingDataSpace() const { + return mConsumer->getCurrentDataSpace(); +} + +Rect BufferQueueLayer::getDrawingCrop() const { + return mConsumer->getCurrentCrop(); +} + +uint32_t BufferQueueLayer::getDrawingScalingMode() const { + return mConsumer->getCurrentScalingMode(); +} + +Region BufferQueueLayer::getDrawingSurfaceDamage() const { + return mConsumer->getSurfaceDamage(); +} + +const HdrMetadata& BufferQueueLayer::getDrawingHdrMetadata() const { + return mConsumer->getCurrentHdrMetadata(); +} + +int BufferQueueLayer::getDrawingApi() const { + return mConsumer->getCurrentApi(); +} + +PixelFormat BufferQueueLayer::getPixelFormat() const { + return mFormat; +} + +uint64_t BufferQueueLayer::getFrameNumber() const { + Mutex::Autolock lock(mQueueItemLock); + return mQueueItems[0].mFrameNumber; +} + +bool BufferQueueLayer::getAutoRefresh() const { + return mAutoRefresh; +} + +bool BufferQueueLayer::getSidebandStreamChanged() const { + return mSidebandStreamChanged; +} + +std::optional BufferQueueLayer::latchSidebandStream(bool& recomputeVisibleRegions) { + if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) { + // mSidebandStreamChanged was true + // replicated in LayerBE until FE/BE is ready to be synchronized + getBE().compositionInfo.hwc.sidebandStream = mConsumer->getSidebandStream(); + if (getBE().compositionInfo.hwc.sidebandStream != nullptr) { + setTransactionFlags(eTransactionNeeded); + mFlinger->setTransactionFlags(eTraversalNeeded); + } + recomputeVisibleRegions = true; + + const State& s(getDrawingState()); + return getTransform().transform(Region(Rect(s.active.w, s.active.h))); + } + return {}; +} + +bool BufferQueueLayer::hasDrawingBuffer() const { + return mQueuedFrames > 0; +} + +void BufferQueueLayer::setFilteringEnabled(bool enabled) const { + return mConsumer->setFilteringEnabled(enabled); +} + +status_t BufferQueueLayer::bindTextureImage() const { + return mConsumer->bindTextureImage(); +} + +status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) { + // 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, + getTransformToDisplayInverse(), mFreezeGeometryUpdates); + status_t updateResult = mConsumer->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 BAD_VALUE; + } else if (updateResult == BufferLayerConsumer::BUFFER_REJECTED) { + // If the buffer has been rejected, remove it from the shadow queue + // and return early + if (queuedBuffer) { + Mutex::Autolock lock(mQueueItemLock); + mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber); + mQueueItems.removeAt(0); + android_atomic_dec(&mQueuedFrames); + } + return BAD_VALUE; + } 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); + mTimeStats.clearLayerRecord(getName().c_str()); + } + + // 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 BAD_VALUE; + } + + if (queuedBuffer) { + // Autolock scope + auto currentFrameNumber = mConsumer->getFrameNumber(); + + Mutex::Autolock lock(mQueueItemLock); + + // Remove any stale buffers that have been dropped during + // updateTexImage + while (mQueueItems[0].mFrameNumber != currentFrameNumber) { + mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber); + mQueueItems.removeAt(0); + android_atomic_dec(&mQueuedFrames); + } + + const std::string layerName(getName().c_str()); + mTimeStats.setAcquireFence(layerName, currentFrameNumber, mQueueItems[0].mFenceTime); + mTimeStats.setLatchTime(layerName, currentFrameNumber, latchTime); + + 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(); + } + + return NO_ERROR; +} + +status_t BufferQueueLayer::updateActiveBuffer() { + // update the active buffer + mActiveBuffer = mConsumer->getCurrentBuffer(&mActiveBufferSlot); + getBE().compositionInfo.mBuffer = mActiveBuffer; + getBE().compositionInfo.mBufferSlot = mActiveBufferSlot; + + if (mActiveBuffer == nullptr) { + // this can only happen if the very first buffer was rejected. + return BAD_VALUE; + } + return NO_ERROR; +} + +status_t BufferQueueLayer::updateFrameNumber(nsecs_t latchTime) { + mPreviousFrameNumber = mCurrentFrameNumber; + mCurrentFrameNumber = mConsumer->getFrameNumber(); + + { + Mutex::Autolock lock(mFrameEventHistoryMutex); + mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime); + } + return NO_ERROR; +} + +void BufferQueueLayer::setHwcLayerBuffer(const sp& display) { + const auto displayId = display->getId(); + auto& hwcInfo = getBE().mHwcLayers[displayId]; + auto& hwcLayer = hwcInfo.layer; + + uint32_t hwcSlot = 0; + sp hwcBuffer; + hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, &hwcSlot, &hwcBuffer); + + auto acquireFence = mConsumer->getCurrentFence(); + auto error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), + getBE().compositionInfo.mBuffer->handle, to_string(error).c_str(), + static_cast(error)); + } +} + +// ----------------------------------------------------------------------- +// Interface implementation for BufferLayerConsumer::ContentsChangedListener +// ----------------------------------------------------------------------- + +void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { + // Add this buffer from our internal queue tracker + { // Autolock scope + Mutex::Autolock lock(mQueueItemLock); + // 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->mInterceptor->saveBufferUpdate(this, item.mGraphicBuffer->getWidth(), + item.mGraphicBuffer->getHeight(), item.mFrameNumber); + mFlinger->signalLayerUpdate(); +} + +void BufferQueueLayer::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 (!hasDrawingBuffer()) { + 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 BufferQueueLayer::onSidebandStreamChanged() { + if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) { + // mSidebandStreamChanged was false + mFlinger->signalLayerUpdate(); + } +} + +// ----------------------------------------------------------------------- + +void BufferQueueLayer::onFirstRef() { + // Creates a custom BufferQueue for SurfaceFlingerConsumer to use + sp producer; + sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer, true); + mProducer = new MonitoredProducer(producer, mFlinger, this); + { + // Grab the SF state lock during this since it's the only safe way to access RenderEngine + Mutex::Autolock lock(mFlinger->mStateLock); + mConsumer = + new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this); + } + mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); + mConsumer->setContentsChangedListener(this); + mConsumer->setName(mName); + + if (mFlinger->isLayerTripleBufferingDisabled()) { + mProducer->setMaxDequeuedBufferCount(2); + } +} + +status_t BufferQueueLayer::setDefaultBufferProperties(uint32_t w, uint32_t h, PixelFormat format) { + 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; + + setDefaultBufferSize(w, h); + mConsumer->setDefaultBufferFormat(format); + mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); + + return NO_ERROR; +} + +sp BufferQueueLayer::getProducer() const { + return mProducer; +} + +uint32_t BufferQueueLayer::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(producerStickyTransform); +} + +} // namespace android diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h new file mode 100644 index 0000000000..7454e2058a --- /dev/null +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2018 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 "BufferLayer.h" + +#include + +namespace android { + +/* + * A new BufferQueue and a new BufferLayerConsumer are created when the + * BufferLayer is first referenced. + * + * This also implements onFrameAvailable(), which notifies SurfaceFlinger + * that new data has arrived. + */ +class BufferQueueLayer : public BufferLayer, public BufferLayerConsumer::ContentsChangedListener { +public: + BufferQueueLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, + uint32_t w, uint32_t h, uint32_t flags); + + // ----------------------------------------------------------------------- + // Interface implementation for Layer + // ----------------------------------------------------------------------- +public: + void onLayerDisplayed(const sp& releaseFence) override; + + void abandon() override; + + void setTransformHint(uint32_t orientation) const override; + + std::vector getOccupancyHistory(bool forceFlush) override; + + bool getTransformToDisplayInverse() const override; + + // If a buffer was replaced this frame, release the former buffer + void releasePendingBuffer(nsecs_t dequeueReadyTime) override; + + void setDefaultBufferSize(uint32_t w, uint32_t h) override; + + int32_t getQueuedFrameCount() const override; + + bool shouldPresentNow(const DispSync& dispSync) const override; + // ----------------------------------------------------------------------- + + // ----------------------------------------------------------------------- + // Interface implementation for BufferLayer + // ----------------------------------------------------------------------- +public: + bool fenceHasSignaled() const override; + +private: + nsecs_t getDesiredPresentTime() override; + std::shared_ptr getCurrentFenceTime() const override; + + void getDrawingTransformMatrix(float matrix[16]) const override; + uint32_t getDrawingTransform() const override; + ui::Dataspace getDrawingDataSpace() const override; + Rect getDrawingCrop() const override; + uint32_t getDrawingScalingMode() const override; + Region getDrawingSurfaceDamage() const override; + const HdrMetadata& getDrawingHdrMetadata() const override; + int getDrawingApi() const override; + PixelFormat getPixelFormat() const override; + + uint64_t getFrameNumber() const override; + + bool getAutoRefresh() const override; + bool getSidebandStreamChanged() const override; + + std::optional latchSidebandStream(bool& recomputeVisibleRegions) override; + + bool hasDrawingBuffer() const override; + + void setFilteringEnabled(bool enabled) const override; + + status_t bindTextureImage() const override; + status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override; + + status_t updateActiveBuffer() override; + status_t updateFrameNumber(nsecs_t latchTime) override; + + void setHwcLayerBuffer(const sp& display) override; + // ----------------------------------------------------------------------- + + // ----------------------------------------------------------------------- + // Interface implementation for BufferLayerConsumer::ContentsChangedListener + // ----------------------------------------------------------------------- +protected: + void onFrameAvailable(const BufferItem& item) override; + void onFrameReplaced(const BufferItem& item) override; + void onSidebandStreamChanged() override; + // ----------------------------------------------------------------------- + +public: + status_t setDefaultBufferProperties(uint32_t w, uint32_t h, PixelFormat format); + + sp getProducer() const; + +private: + // Temporary - Used only for LEGACY camera mode. + uint32_t getProducerStickyTransform() const; + + void onFirstRef() override; + + sp mConsumer; + sp mProducer; + + PixelFormat mFormat; + + // Only accessed on the main thread. + uint64_t mPreviousFrameNumber; + bool mUpdateTexImageFailed; + + // Local copy of the queued contents of the incoming BufferQueue + mutable Mutex mQueueItemLock; + Condition mQueueItemCondition; + Vector mQueueItems; + std::atomic mLastFrameNumberReceived; + + bool mAutoRefresh; + int mActiveBufferSlot; + + // thread-safe + volatile int32_t mQueuedFrames; + volatile int32_t mSidebandStreamChanged; // used like an atomic boolean +}; + +} // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 40d89bdb10..b58269eb32 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -75,12 +75,8 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n mTransactionFlags(0), mPendingStateMutex(), mPendingStates(), - mQueuedFrames(0), - mSidebandStreamChanged(false), - mActiveBufferSlot(BufferQueue::INVALID_BUFFER_SLOT), mCurrentTransform(0), mOverrideScalingMode(-1), - mCurrentOpacity(true), mCurrentFrameNumber(0), mFrameLatencyNeeded(false), mFiltering(false), @@ -88,11 +84,6 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n mProtectedByApp(false), mClientRef(client), mPotentialCursor(false), - mQueueItemLock(), - mQueueItemCondition(), - mQueueItems(), - mLastFrameNumberReceived(0), - mAutoRefresh(false), mFreezeGeometryUpdates(false), mCurrentChildren(LayerVector::StateSet::Current), mDrawingChildren(LayerVector::StateSet::Drawing), diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index f72409652d..94f086cafe 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -425,7 +425,6 @@ public: virtual bool isBufferLatched() const { return false; } - 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 @@ -449,13 +448,11 @@ public: Rect getContentCrop() const; /* - * Returns if a frame is queued. + * Returns if a frame is ready */ - bool hasQueuedFrame() const { - return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh; - } + virtual bool hasReadyFrame() const { return false; } - int32_t getQueuedFrameCount() const { return mQueuedFrames; } + virtual int32_t getQueuedFrameCount() const { return 0; } // ----------------------------------------------------------------------- @@ -674,10 +671,6 @@ protected: Mutex mPendingStateMutex; Vector mPendingStates; - // thread-safe - volatile int32_t mQueuedFrames; - volatile int32_t mSidebandStreamChanged; // used like an atomic boolean - // Timestamp history for UIAutomation. Thread safe. FrameTracker mFrameTracker; @@ -691,15 +684,12 @@ protected: TimeStats& mTimeStats = TimeStats::getInstance(); // main thread - int mActiveBufferSlot; sp mActiveBuffer; - sp mSidebandStream; ui::Dataspace mCurrentDataSpace = ui::Dataspace::UNKNOWN; Rect mCurrentCrop; uint32_t mCurrentTransform; // We encode unset as -1. int32_t mOverrideScalingMode; - bool mCurrentOpacity; std::atomic mCurrentFrameNumber; bool mFrameLatencyNeeded; // Whether filtering is forced on or not @@ -720,12 +710,6 @@ protected: // This layer can be a cursor on some displays. bool mPotentialCursor; - // Local copy of the queued contents of the incoming BufferQueue - mutable Mutex mQueueItemLock; - Condition mQueueItemCondition; - Vector mQueueItems; - std::atomic mLastFrameNumberReceived; - bool mAutoRefresh; bool mFreezeGeometryUpdates; // Child list about to be committed/used for editing. diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 9aa43f7fd3..8b371705f1 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -77,6 +77,7 @@ class LayerBE { public: friend class Layer; friend class BufferLayer; + friend class BufferQueueLayer; friend class ColorLayer; friend class SurfaceFlinger; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index ba5154d8e7..64520d0979 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -63,6 +63,7 @@ #include #include "BufferLayer.h" +#include "BufferQueueLayer.h" #include "Client.h" #include "ColorLayer.h" #include "Colorizer.h" @@ -2869,7 +2870,7 @@ bool SurfaceFlinger::handlePageFlip() // Display is now waiting on Layer 1's frame, which is behind layer 0's // second frame. But layer 0's second frame could be waiting on display. mDrawingState.traverseInZOrder([&](Layer* layer) { - if (layer->hasQueuedFrame()) { + if (layer->hasReadyFrame()) { frameQueued = true; if (layer->shouldPresentNow(mPrimaryDispSync)) { mLayersWithQueuedFrames.push_back(layer); @@ -3593,9 +3594,8 @@ status_t SurfaceFlinger::createLayer( switch (flags & ISurfaceComposerClient::eFXSurfaceMask) { case ISurfaceComposerClient::eFXSurfaceNormal: - result = createBufferLayer(client, - uniqueName, w, h, flags, format, - handle, gbp, &layer); + result = createBufferQueueLayer(client, uniqueName, w, h, flags, format, handle, gbp, + &layer); break; case ISurfaceComposerClient::eFXSurfaceColor: @@ -3659,10 +3659,11 @@ String8 SurfaceFlinger::getUniqueLayerName(const String8& name) return uniqueName; } -status_t SurfaceFlinger::createBufferLayer(const sp& client, - const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format, - sp* handle, sp* gbp, sp* outLayer) -{ +status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, const String8& name, + uint32_t w, uint32_t h, uint32_t flags, + PixelFormat& format, sp* handle, + sp* gbp, + sp* outLayer) { // initialize the surfaces switch (format) { case PIXEL_FORMAT_TRANSPARENT: @@ -3674,15 +3675,15 @@ status_t SurfaceFlinger::createBufferLayer(const sp& client, break; } - sp layer = new BufferLayer(this, client, name, w, h, flags); - status_t err = layer->setBuffers(w, h, format, flags); + sp layer = new BufferQueueLayer(this, client, name, w, h, flags); + status_t err = layer->setDefaultBufferProperties(w, h, format); if (err == NO_ERROR) { *handle = layer->getHandle(); *gbp = layer->getProducer(); *outLayer = layer; } - ALOGE_IF(err, "createBufferLayer() failed (%s)", strerror(-err)); + ALOGE_IF(err, "createBufferQueueLayer() failed (%s)", strerror(-err)); return err; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index e107f425be..a750636520 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -355,6 +355,7 @@ private: friend class impl::EventThread; friend class Layer; friend class BufferLayer; + friend class BufferQueueLayer; friend class MonitoredProducer; // For unit tests @@ -529,10 +530,10 @@ private: int32_t windowType, int32_t ownerUid, sp* handle, sp* gbp, sp* parent); - status_t createBufferLayer(const sp& client, const String8& name, - uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format, - sp* outHandle, sp* outGbp, - sp* outLayer); + status_t createBufferQueueLayer(const sp& client, const String8& name, uint32_t w, + uint32_t h, uint32_t flags, PixelFormat& format, + sp* outHandle, sp* outGbp, + sp* outLayer); status_t createColorLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, sp* outHandle, -- cgit v1.2.3-59-g8ed1b From f58c14b3d51f2face21c9759149b5c9412bcafd5 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Tue, 24 Jul 2018 10:50:43 -0700 Subject: blast: Append "_legacy" to old buffer state values As we move from BufferQueueLayer to BufferStateLayer, some layer state fields are used by both layer types and some are used exclusively by one type of layer. Append "_legacy" to all fields that are NOT used by BufferStateLayer. Bug: 80477568 Test: Transaction_test.cpp Change-Id: Id8bf27f5b68c00592136e4336442a5d388f35779 --- cmds/surfacereplayer/replayer/Replayer.cpp | 6 +- libs/gui/LayerState.cpp | 43 ++-- libs/gui/SurfaceComposerClient.cpp | 39 +-- libs/gui/include/gui/LayerState.h | 22 +- libs/gui/include/gui/SurfaceComposerClient.h | 17 +- services/surfaceflinger/BufferLayer.cpp | 14 +- services/surfaceflinger/BufferQueueLayer.cpp | 4 +- services/surfaceflinger/Layer.cpp | 261 +++++++++++---------- services/surfaceflinger/Layer.h | 28 +-- services/surfaceflinger/LayerRejecter.cpp | 49 ++-- services/surfaceflinger/SurfaceFlinger.cpp | 34 +-- services/surfaceflinger/SurfaceInterceptor.cpp | 43 ++-- .../tests/SurfaceInterceptor_test.cpp | 7 +- services/surfaceflinger/tests/Transaction_test.cpp | 78 +++--- .../tests/fakehwc/SFFakeHwc_test.cpp | 44 ++-- 15 files changed, 353 insertions(+), 336 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index 4140f40888..d9ff4ba59f 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -489,7 +489,7 @@ void Replayer::setCrop(SurfaceComposerClient::Transaction& t, Rect r = Rect(cc.rectangle().left(), cc.rectangle().top(), cc.rectangle().right(), cc.rectangle().bottom()); - t.setCrop(mLayers[id], r); + t.setCrop_legacy(mLayers[id], r); } void Replayer::setFinalCrop(SurfaceComposerClient::Transaction& t, @@ -499,7 +499,7 @@ void Replayer::setFinalCrop(SurfaceComposerClient::Transaction& t, fcc.rectangle().bottom()); Rect r = Rect(fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(), fcc.rectangle().bottom()); - t.setFinalCrop(mLayers[id], r); + t.setFinalCrop_legacy(mLayers[id], r); } void Replayer::setMatrix(SurfaceComposerClient::Transaction& t, @@ -570,7 +570,7 @@ void Replayer::setDeferredTransaction(SurfaceComposerClient::Transaction& t, auto handle = mLayers[dtc.layer_id()]->getHandle(); - t.deferTransactionUntil(mLayers[id], handle, dtc.frame_number()); + t.deferTransactionUntil_legacy(mLayers[id], handle, dtc.frame_number()); } void Replayer::setDisplaySurface(SurfaceComposerClient::Transaction& t, diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 01acc2de20..0414a486e6 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -37,13 +37,13 @@ status_t layer_state_t::write(Parcel& output) const output.writeUint32(mask); *reinterpret_cast( output.writeInplace(sizeof(layer_state_t::matrix22_t))) = matrix; - output.write(crop); - output.write(finalCrop); - output.writeStrongBinder(barrierHandle); + output.write(crop_legacy); + output.write(finalCrop_legacy); + output.writeStrongBinder(barrierHandle_legacy); output.writeStrongBinder(reparentHandle); - output.writeUint64(frameNumber); + output.writeUint64(frameNumber_legacy); output.writeInt32(overrideScalingMode); - output.writeStrongBinder(IInterface::asBinder(barrierGbp)); + output.writeStrongBinder(IInterface::asBinder(barrierGbp_legacy)); output.writeStrongBinder(relativeLayerHandle); output.writeStrongBinder(parentHandleForChild); output.writeFloat(color.r); @@ -72,14 +72,13 @@ status_t layer_state_t::read(const Parcel& input) } else { return BAD_VALUE; } - input.read(crop); - input.read(finalCrop); - barrierHandle = input.readStrongBinder(); + input.read(crop_legacy); + input.read(finalCrop_legacy); + barrierHandle_legacy = input.readStrongBinder(); reparentHandle = input.readStrongBinder(); - frameNumber = input.readUint64(); + frameNumber_legacy = input.readUint64(); overrideScalingMode = input.readInt32(); - barrierGbp = - interface_cast(input.readStrongBinder()); + barrierGbp_legacy = interface_cast(input.readStrongBinder()); relativeLayerHandle = input.readStrongBinder(); parentHandleForChild = input.readStrongBinder(); color.r = input.readFloat(); @@ -194,19 +193,19 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eLayerStackChanged; layerStack = other.layerStack; } - if (other.what & eCropChanged) { - what |= eCropChanged; - crop = other.crop; + if (other.what & eCropChanged_legacy) { + what |= eCropChanged_legacy; + crop_legacy = other.crop_legacy; } - if (other.what & eDeferTransaction) { - what |= eDeferTransaction; - barrierHandle = other.barrierHandle; - barrierGbp = other.barrierGbp; - frameNumber = other.frameNumber; + if (other.what & eDeferTransaction_legacy) { + what |= eDeferTransaction_legacy; + barrierHandle_legacy = other.barrierHandle_legacy; + barrierGbp_legacy = other.barrierGbp_legacy; + frameNumber_legacy = other.frameNumber_legacy; } - if (other.what & eFinalCropChanged) { - what |= eFinalCropChanged; - finalCrop = other.finalCrop; + if (other.what & eFinalCropChanged_legacy) { + what |= eFinalCropChanged_legacy; + finalCrop_legacy = other.finalCrop_legacy; } if (other.what & eOverrideScalingModeChanged) { what |= eOverrideScalingModeChanged; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index fc076d2ea5..3ff0ec20ea 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -344,54 +344,57 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setMatri return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCrop( +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCrop_legacy( const sp& sc, const Rect& crop) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } - s->what |= layer_state_t::eCropChanged; - s->crop = crop; + s->what |= layer_state_t::eCropChanged_legacy; + s->crop_legacy = crop; return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFinalCrop(const sp& sc, const Rect& crop) { +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFinalCrop_legacy( + const sp& sc, const Rect& crop) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } - s->what |= layer_state_t::eFinalCropChanged; - s->finalCrop = crop; + s->what |= layer_state_t::eFinalCropChanged_legacy; + s->finalCrop_legacy = crop; return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTransactionUntil( - const sp& sc, - const sp& handle, uint64_t frameNumber) { +SurfaceComposerClient::Transaction& +SurfaceComposerClient::Transaction::deferTransactionUntil_legacy(const sp& sc, + const sp& handle, + uint64_t frameNumber) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } - s->what |= layer_state_t::eDeferTransaction; - s->barrierHandle = handle; - s->frameNumber = frameNumber; + s->what |= layer_state_t::eDeferTransaction_legacy; + s->barrierHandle_legacy = handle; + s->frameNumber_legacy = frameNumber; return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTransactionUntil( - const sp& sc, - const sp& barrierSurface, uint64_t frameNumber) { +SurfaceComposerClient::Transaction& +SurfaceComposerClient::Transaction::deferTransactionUntil_legacy(const sp& sc, + const sp& barrierSurface, + uint64_t frameNumber) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } - s->what |= layer_state_t::eDeferTransaction; - s->barrierGbp = barrierSurface->getIGraphicBufferProducer(); - s->frameNumber = frameNumber; + s->what |= layer_state_t::eDeferTransaction_legacy; + s->barrierGbp_legacy = barrierSurface->getIGraphicBufferProducer(); + s->frameNumber_legacy = frameNumber; return *this; } diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index a343c2f0f5..b88b7fe118 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -51,9 +51,9 @@ struct layer_state_t { eTransparentRegionChanged = 0x00000020, eFlagsChanged = 0x00000040, eLayerStackChanged = 0x00000080, - eCropChanged = 0x00000100, - eDeferTransaction = 0x00000200, - eFinalCropChanged = 0x00000400, + eCropChanged_legacy = 0x00000100, + eDeferTransaction_legacy = 0x00000200, + eFinalCropChanged_legacy = 0x00000400, eOverrideScalingModeChanged = 0x00000800, eGeometryAppliesWithResize = 0x00001000, eReparentChildren = 0x00002000, @@ -76,9 +76,9 @@ struct layer_state_t { flags(0), mask(0), reserved(0), - crop(Rect::INVALID_RECT), - finalCrop(Rect::INVALID_RECT), - frameNumber(0), + crop_legacy(Rect::INVALID_RECT), + finalCrop_legacy(Rect::INVALID_RECT), + frameNumber_legacy(0), overrideScalingMode(-1) { matrix.dsdx = matrix.dtdy = 1.0f; matrix.dsdy = matrix.dtdx = 0.0f; @@ -107,14 +107,14 @@ struct layer_state_t { uint8_t mask; uint8_t reserved; matrix22_t matrix; - Rect crop; - Rect finalCrop; - sp barrierHandle; + Rect crop_legacy; + Rect finalCrop_legacy; + sp barrierHandle_legacy; sp reparentHandle; - uint64_t frameNumber; + uint64_t frameNumber_legacy; int32_t overrideScalingMode; - sp barrierGbp; + sp barrierGbp_legacy; sp relativeLayerHandle; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 34708c755f..278a642c91 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -200,22 +200,21 @@ public: float alpha); Transaction& setMatrix(const sp& sc, float dsdx, float dtdx, float dtdy, float dsdy); - Transaction& setCrop(const sp& sc, const Rect& crop); - Transaction& setFinalCrop(const sp& sc, const Rect& crop); + Transaction& setCrop_legacy(const sp& sc, const Rect& crop); + Transaction& setFinalCrop_legacy(const sp& sc, const Rect& crop); Transaction& setLayerStack(const sp& sc, uint32_t layerStack); // Defers applying any changes made in this transaction until the Layer // identified by handle reaches the given frameNumber. If the Layer identified // by handle is removed, then we will apply this transaction regardless of // what frame number has been reached. - Transaction& deferTransactionUntil(const sp& sc, - const sp& handle, - uint64_t frameNumber); - // A variant of deferTransactionUntil which identifies the Layer we wait for by + Transaction& deferTransactionUntil_legacy(const sp& sc, + const sp& handle, uint64_t frameNumber); + // A variant of deferTransactionUntil_legacy which identifies the Layer we wait for by // Surface instead of Handle. Useful for clients which may not have the // SurfaceControl for some of their Surfaces. Otherwise behaves identically. - Transaction& deferTransactionUntil(const sp& sc, - const sp& barrierSurface, - uint64_t frameNumber); + Transaction& deferTransactionUntil_legacy(const sp& sc, + const sp& barrierSurface, + uint64_t frameNumber); // Reparents all children of this layer to the new parent handle. Transaction& reparentChildren(const sp& sc, const sp& newParentHandle); diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 7246c8e890..64842450fa 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -518,7 +518,7 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime // FIXME: postedRegion should be dirty & bounds // transform the dirty region to window-manager space - return getTransform().transform(Region(Rect(s.active.w, s.active.h))); + return getTransform().transform(Region(Rect(s.active_legacy.w, s.active_legacy.h))); } // transaction @@ -641,9 +641,9 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT Transform t = getTransform(); Rect win = bounds; - if (!s.finalCrop.isEmpty()) { + if (!s.finalCrop_legacy.isEmpty()) { win = t.transform(win); - if (!win.intersect(s.finalCrop, &win)) { + if (!win.intersect(s.finalCrop_legacy, &win)) { win.clear(); } win = t.inverse().transform(win); @@ -652,10 +652,10 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT } } - 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); + float left = float(win.left) / float(s.active_legacy.w); + float top = float(win.top) / float(s.active_legacy.h); + float right = float(win.right) / float(s.active_legacy.w); + float bottom = float(win.bottom) / float(s.active_legacy.h); // TODO: we probably want to generate the texture coords with the mesh // here we assume that we only have 4 vertices diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index d5a94b7c6a..1bf9cf275b 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -38,7 +38,7 @@ BufferQueueLayer::BufferQueueLayer(SurfaceFlinger* flinger, const sp& cl mActiveBufferSlot(BufferQueue::INVALID_BUFFER_SLOT), mQueuedFrames(0), mSidebandStreamChanged(false) { - mCurrentState.requested = mCurrentState.active; + mCurrentState.requested_legacy = mCurrentState.active_legacy; } // ----------------------------------------------------------------------- @@ -219,7 +219,7 @@ std::optional BufferQueueLayer::latchSidebandStream(bool& recomputeVisib recomputeVisibleRegions = true; const State& s(getDrawingState()); - return getTransform().transform(Region(Rect(s.active.w, s.active.h))); + return getTransform().transform(Region(Rect(s.active_legacy.w, s.active_legacy.h))); } return {}; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index b58269eb32..eeee0ae863 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -99,19 +99,19 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n mName = name; mTransactionName = String8("TX - ") + mName; - mCurrentState.active.w = w; - mCurrentState.active.h = h; + mCurrentState.active_legacy.w = w; + mCurrentState.active_legacy.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.active_legacy.transform.set(0, 0); + mCurrentState.crop_legacy.makeInvalid(); + mCurrentState.finalCrop_legacy.makeInvalid(); + mCurrentState.requestedFinalCrop_legacy = mCurrentState.finalCrop_legacy; + mCurrentState.requestedCrop_legacy = mCurrentState.crop_legacy; mCurrentState.z = 0; mCurrentState.color.a = 1.0f; mCurrentState.layerStack = 0; mCurrentState.sequence = 0; - mCurrentState.requested = mCurrentState.active; + mCurrentState.requested_legacy = mCurrentState.active_legacy; mCurrentState.appId = 0; mCurrentState.type = 0; @@ -293,17 +293,17 @@ static FloatRect reduce(const FloatRect& win, const Region& exclude) { Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { const Layer::State& s(getDrawingState()); - Rect win(s.active.w, s.active.h); + Rect win(s.active_legacy.w, s.active_legacy.h); - if (!s.crop.isEmpty()) { - win.intersect(s.crop, &win); + if (!s.crop_legacy.isEmpty()) { + win.intersect(s.crop_legacy, &win); } Transform t = getTransform(); win = t.transform(win); - if (!s.finalCrop.isEmpty()) { - win.intersect(s.finalCrop, &win); + if (!s.finalCrop_legacy.isEmpty()) { + win.intersect(s.finalCrop_legacy, &win); } const sp& p = mDrawingParent.promote(); @@ -322,7 +322,7 @@ Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { } if (reduceTransparentRegion) { - auto const screenTransparentRegion = t.transform(s.activeTransparentRegion); + auto const screenTransparentRegion = t.transform(s.activeTransparentRegion_legacy); win = reduce(win, screenTransparentRegion); } @@ -331,15 +331,15 @@ Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { FloatRect Layer::computeBounds() const { const Layer::State& s(getDrawingState()); - return computeBounds(s.activeTransparentRegion); + return computeBounds(s.activeTransparentRegion_legacy); } FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const { const Layer::State& s(getDrawingState()); - Rect win(s.active.w, s.active.h); + Rect win(s.active_legacy.w, s.active_legacy.h); - if (!s.crop.isEmpty()) { - win.intersect(s.crop, &win); + if (!s.crop_legacy.isEmpty()) { + win.intersect(s.crop_legacy, &win); } const auto& p = mDrawingParent.promote(); @@ -351,15 +351,14 @@ FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const { parentBounds = p->computeBounds(Region()); } - Transform t = s.active.transform; + Transform t = s.active_legacy.transform; - - if (p != nullptr || !s.finalCrop.isEmpty()) { + if (p != nullptr || !s.finalCrop_legacy.isEmpty()) { floatWin = t.transform(floatWin); floatWin = floatWin.intersect(parentBounds); - if (!s.finalCrop.isEmpty()) { - floatWin = floatWin.intersect(s.finalCrop.toFloatRect()); + if (!s.finalCrop_legacy.isEmpty()) { + floatWin = floatWin.intersect(s.finalCrop_legacy.toFloatRect()); } floatWin = t.inverse().transform(floatWin); } @@ -380,9 +379,9 @@ Rect Layer::computeInitialCrop(const sp& display) const { // FIXME: the 3 lines below can produce slightly incorrect clipping when we have // a viewport clipping and a window transform. we should use floating point to fix this. - Rect activeCrop(s.active.w, s.active.h); - if (!s.crop.isEmpty()) { - activeCrop.intersect(s.crop, &activeCrop); + Rect activeCrop(s.active_legacy.w, s.active_legacy.h); + if (!s.crop_legacy.isEmpty()) { + activeCrop.intersect(s.crop_legacy, &activeCrop); } Transform t = getTransform(); @@ -390,8 +389,8 @@ Rect Layer::computeInitialCrop(const sp& display) const { if (!activeCrop.intersect(display->getViewport(), &activeCrop)) { activeCrop.clear(); } - if (!s.finalCrop.isEmpty()) { - if (!activeCrop.intersect(s.finalCrop, &activeCrop)) { + if (!s.finalCrop_legacy.isEmpty()) { + if (!activeCrop.intersect(s.finalCrop_legacy, &activeCrop)) { activeCrop.clear(); } } @@ -425,12 +424,12 @@ FloatRect Layer::computeCrop(const sp& display) const { // 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_legacy.w, s.active_legacy.h), &activeCrop)) { activeCrop.clear(); } // subtract the transparent region and snap to the bounds - activeCrop = reduce(activeCrop, s.activeTransparentRegion); + activeCrop = reduce(activeCrop, s.activeTransparentRegion_legacy); // Transform the window crop to match the buffer coordinate system, // which means using the inverse of the current transform set on the @@ -450,8 +449,8 @@ FloatRect Layer::computeCrop(const sp& display) const { invTransform = (Transform(invTransformOrient) * Transform(invTransform)).getOrientation(); } - int winWidth = s.active.w; - int winHeight = s.active.h; + int winWidth = s.active_legacy.w; + int winHeight = s.active_legacy.h; if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { // If the activeCrop has been rotate the ends are rotated but not // the space itself so when transforming ends back we can't rely on @@ -463,10 +462,10 @@ FloatRect Layer::computeCrop(const sp& display) const { if (is_h_flipped == is_v_flipped) { invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H; } - winWidth = s.active.h; - winHeight = s.active.w; + winWidth = s.active_legacy.h; + winHeight = s.active_legacy.w; } - const Rect winCrop = activeCrop.transform(invTransform, s.active.w, s.active.h); + const Rect winCrop = activeCrop.transform(invTransform, s.active_legacy.w, s.active_legacy.h); // below, crop is intersected with winCrop expressed in crop's coordinate space float xScale = crop.getWidth() / float(winWidth); @@ -519,10 +518,10 @@ void Layer::setGeometry(const sp& display, uint32_t z) { // apply the layer's transform, followed by the display's global transform // here we're guaranteed that the layer's transform preserves rects - Region activeTransparentRegion(s.activeTransparentRegion); + Region activeTransparentRegion(s.activeTransparentRegion_legacy); Transform t = getTransform(); - if (!s.crop.isEmpty()) { - Rect activeCrop(s.crop); + if (!s.crop_legacy.isEmpty()) { + Rect activeCrop(s.crop_legacy); activeCrop = t.transform(activeCrop); if (!activeCrop.intersect(display->getViewport(), &activeCrop)) { activeCrop.clear(); @@ -534,22 +533,23 @@ void Layer::setGeometry(const sp& display, uint32_t z) { // 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_legacy.w, s.active_legacy.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, 0, s.active_legacy.w, activeCrop.top)); + activeTransparentRegion.orSelf( + Rect(0, activeCrop.bottom, s.active_legacy.w, s.active_legacy.h)); activeTransparentRegion.orSelf(Rect(0, activeCrop.top, activeCrop.left, activeCrop.bottom)); activeTransparentRegion.orSelf( - Rect(activeCrop.right, activeCrop.top, s.active.w, activeCrop.bottom)); + Rect(activeCrop.right, activeCrop.top, s.active_legacy.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 (!s.finalCrop_legacy.isEmpty()) { + if (!frame.intersect(s.finalCrop_legacy, &frame)) { frame.clear(); } } @@ -682,16 +682,16 @@ void Layer::updateCursorPosition(const sp& display) { // 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); + Rect win(s.active_legacy.w, s.active_legacy.h); + if (!s.crop_legacy.isEmpty()) { + win.intersect(s.crop_legacy, &win); } // Subtract the transparent region and snap to the bounds - Rect bounds = reduce(win, s.activeTransparentRegion); + Rect bounds = reduce(win, s.activeTransparentRegion_legacy); Rect frame(getTransform().transform(bounds)); frame.intersect(display->getViewport(), &frame); - if (!s.finalCrop.isEmpty()) { - frame.intersect(s.finalCrop, &frame); + if (!s.finalCrop_legacy.isEmpty()) { + frame.intersect(s.finalCrop_legacy, &frame); } auto& displayTransform = display->getTransform(); auto position = displayTransform.transform(frame); @@ -844,11 +844,11 @@ void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh, rt = layerTransform.transform(rt); } - if (!s.finalCrop.isEmpty()) { - boundPoint(<, s.finalCrop); - boundPoint(&lb, s.finalCrop); - boundPoint(&rb, s.finalCrop); - boundPoint(&rt, s.finalCrop); + if (!s.finalCrop_legacy.isEmpty()) { + boundPoint(<, s.finalCrop_legacy); + boundPoint(&lb, s.finalCrop_legacy); + boundPoint(&rb, s.finalCrop_legacy); + boundPoint(&rt, s.finalCrop_legacy); } Mesh::VertexArray position(mesh.getPositionArray()); @@ -898,22 +898,22 @@ void Layer::pushPendingState() { // If this transaction is waiting on the receipt of a frame, generate a sync // point and send it to the remote layer. - if (mCurrentState.barrierLayer != nullptr) { - sp barrierLayer = mCurrentState.barrierLayer.promote(); + if (mCurrentState.barrierLayer_legacy != nullptr) { + sp barrierLayer = mCurrentState.barrierLayer_legacy.promote(); if (barrierLayer == nullptr) { ALOGE("[%s] Unable to promote barrier Layer.", mName.string()); // If we can't promote the layer we are intended to wait on, // then it is expired or otherwise invalid. Allow this transaction // to be applied as per normal (no synchronization). - mCurrentState.barrierLayer = nullptr; + mCurrentState.barrierLayer_legacy = nullptr; } else { - auto syncPoint = std::make_shared(mCurrentState.frameNumber); + auto syncPoint = std::make_shared(mCurrentState.frameNumber_legacy); if (barrierLayer->addSyncPoint(syncPoint)) { mRemoteSyncPoints.push_back(std::move(syncPoint)); } else { // We already missed the frame we're supposed to synchronize // on, so go ahead and apply the state update - mCurrentState.barrierLayer = nullptr; + mCurrentState.barrierLayer_legacy = nullptr; } } @@ -935,7 +935,7 @@ void Layer::popPendingState(State* stateToCommit) { bool Layer::applyPendingStates(State* stateToCommit) { bool stateUpdateAvailable = false; while (!mPendingStates.empty()) { - if (mPendingStates[0].barrierLayer != nullptr) { + if (mPendingStates[0].barrierLayer_legacy != nullptr) { if (mRemoteSyncPoints.empty()) { // If we don't have a sync point for this, apply it anyway. It // will be visually wrong, but it should keep us from getting @@ -946,7 +946,8 @@ bool Layer::applyPendingStates(State* stateToCommit) { continue; } - if (mRemoteSyncPoints.front()->getFrameNumber() != mPendingStates[0].frameNumber) { + if (mRemoteSyncPoints.front()->getFrameNumber() != + mPendingStates[0].frameNumber_legacy) { ALOGE("[%s] Unexpected sync point frame number found", mName.string()); // Signal our end of the sync point and then dispose of it @@ -994,7 +995,8 @@ 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_legacy.w != s.requested_legacy.w) || + (c.requested_legacy.h != s.requested_legacy.h); if (sizeChanged) { // the size changed, we need to ask our client to request a new buffer @@ -1004,16 +1006,17 @@ uint32_t Layer::doTransaction(uint32_t flags) { " 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); + this, getName().string(), mCurrentTransform, getEffectiveScalingMode(), + c.active_legacy.w, c.active_legacy.h, c.crop_legacy.left, c.crop_legacy.top, + c.crop_legacy.right, c.crop_legacy.bottom, c.crop_legacy.getWidth(), + c.crop_legacy.getHeight(), c.requested_legacy.w, c.requested_legacy.h, + s.active_legacy.w, s.active_legacy.h, s.crop_legacy.left, s.crop_legacy.top, + s.crop_legacy.right, s.crop_legacy.bottom, s.crop_legacy.getWidth(), + s.crop_legacy.getHeight(), s.requested_legacy.w, s.requested_legacy.h); // record the new size, form this point on, when the client request // a buffer, it'll get the new size. - setDefaultBufferSize(c.requested.w, c.requested.h); + setDefaultBufferSize(c.requested_legacy.w, c.requested_legacy.h); } // Don't let Layer::doTransaction update the drawing state @@ -1034,7 +1037,8 @@ uint32_t Layer::doTransaction(uint32_t flags) { // 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)) && + const bool resizePending = ((c.requested_legacy.w != c.active_legacy.w) || + (c.requested_legacy.h != c.active_legacy.h)) && (getBE().compositionInfo.mBuffer != nullptr); if (!isFixedSize()) { if (resizePending && getBE().compositionInfo.hwc.sidebandStream == nullptr) { @@ -1061,18 +1065,18 @@ uint32_t Layer::doTransaction(uint32_t flags) { // Careful that "c" and editCurrentState may not begin as equivalent due to // applyPendingStates in the presence of deferred transactions. if (mFreezeGeometryUpdates) { - float tx = c.active.transform.tx(); - float ty = c.active.transform.ty(); - c.active = c.requested; - c.active.transform.set(tx, ty); - editCurrentState.active = c.active; + float tx = c.active_legacy.transform.tx(); + float ty = c.active_legacy.transform.ty(); + c.active_legacy = c.requested_legacy; + c.active_legacy.transform.set(tx, ty); + editCurrentState.active_legacy = c.active_legacy; } else { - editCurrentState.active = editCurrentState.requested; - c.active = c.requested; + editCurrentState.active_legacy = editCurrentState.requested_legacy; + c.active_legacy = c.requested_legacy; } } - if (s.active != c.active) { + if (s.active_legacy != c.active_legacy) { // invalidate and recompute the visible regions if needed flags |= Layer::eVisibleRegion; } @@ -1083,8 +1087,9 @@ uint32_t Layer::doTransaction(uint32_t flags) { this->contentDirty = true; // 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)); + const uint8_t type = c.active_legacy.transform.getType(); + mNeedsFiltering = + (!c.active_legacy.transform.preserveRects() || (type >= Transform::SCALE)); } // If the layer is hidden, signal and clear out all local sync points so @@ -1112,20 +1117,21 @@ uint32_t Layer::setTransactionFlags(uint32_t flags) { } bool Layer::setPosition(float x, float y, bool immediate) { - if (mCurrentState.requested.transform.tx() == x && mCurrentState.requested.transform.ty() == y) + if (mCurrentState.requested_legacy.transform.tx() == x && + mCurrentState.requested_legacy.transform.ty() == y) return false; mCurrentState.sequence++; // We update the requested and active position simultaneously because // we want to apply the position portion of the transform matrix immediately, // but still delay scaling when resizing a SCALING_MODE_FREEZE layer. - mCurrentState.requested.transform.set(x, y); + mCurrentState.requested_legacy.transform.set(x, y); if (immediate && !mFreezeGeometryUpdates) { // Here we directly update the active state // unlike other setters, because we store it within // the transform, but use different latching rules. // b/38182305 - mCurrentState.active.transform.set(x, y); + mCurrentState.active_legacy.transform.set(x, y); } mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate; @@ -1225,9 +1231,10 @@ bool Layer::setRelativeLayer(const sp& relativeToHandle, int32_t relati } bool Layer::setSize(uint32_t w, uint32_t h) { - if (mCurrentState.requested.w == w && mCurrentState.requested.h == h) return false; - mCurrentState.requested.w = w; - mCurrentState.requested.h = h; + if (mCurrentState.requested_legacy.w == w && mCurrentState.requested_legacy.h == h) + return false; + mCurrentState.requested_legacy.w = w; + mCurrentState.requested_legacy.h = h; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; @@ -1265,13 +1272,14 @@ bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix, return false; } mCurrentState.sequence++; - mCurrentState.requested.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); + mCurrentState.requested_legacy.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, + matrix.dsdy); mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setTransparentRegionHint(const Region& transparent) { - mCurrentState.requestedTransparentRegion = transparent; + mCurrentState.requestedTransparentRegion_legacy = transparent; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; @@ -1286,12 +1294,12 @@ bool Layer::setFlags(uint8_t flags, uint8_t mask) { return true; } -bool Layer::setCrop(const Rect& crop, bool immediate) { - if (mCurrentState.requestedCrop == crop) return false; +bool Layer::setCrop_legacy(const Rect& crop, bool immediate) { + if (mCurrentState.requestedCrop_legacy == crop) return false; mCurrentState.sequence++; - mCurrentState.requestedCrop = crop; + mCurrentState.requestedCrop_legacy = crop; if (immediate && !mFreezeGeometryUpdates) { - mCurrentState.crop = crop; + mCurrentState.crop_legacy = crop; } mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate; @@ -1300,12 +1308,12 @@ bool Layer::setCrop(const Rect& crop, bool immediate) { return true; } -bool Layer::setFinalCrop(const Rect& crop, bool immediate) { - if (mCurrentState.requestedFinalCrop == crop) return false; +bool Layer::setFinalCrop_legacy(const Rect& crop, bool immediate) { + if (mCurrentState.requestedFinalCrop_legacy == crop) return false; mCurrentState.sequence++; - mCurrentState.requestedFinalCrop = crop; + mCurrentState.requestedFinalCrop_legacy = crop; if (immediate && !mFreezeGeometryUpdates) { - mCurrentState.finalCrop = crop; + mCurrentState.finalCrop_legacy = crop; } mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate; @@ -1345,24 +1353,23 @@ uint32_t Layer::getLayerStack() const { return p->getLayerStack(); } -void Layer::deferTransactionUntil(const sp& barrierLayer, uint64_t frameNumber) { - mCurrentState.barrierLayer = barrierLayer; - mCurrentState.frameNumber = frameNumber; +void Layer::deferTransactionUntil_legacy(const sp& barrierLayer, uint64_t frameNumber) { + mCurrentState.barrierLayer_legacy = barrierLayer; + mCurrentState.frameNumber_legacy = frameNumber; // We don't set eTransactionNeeded, because just receiving a deferral // request without any other state updates shouldn't actually induce a delay mCurrentState.modified = true; pushPendingState(); - mCurrentState.barrierLayer = nullptr; - mCurrentState.frameNumber = 0; + mCurrentState.barrierLayer_legacy = nullptr; + mCurrentState.frameNumber_legacy = 0; mCurrentState.modified = false; } -void Layer::deferTransactionUntil(const sp& barrierHandle, uint64_t frameNumber) { +void Layer::deferTransactionUntil_legacy(const sp& barrierHandle, uint64_t frameNumber) { sp handle = static_cast(barrierHandle.get()); - deferTransactionUntil(handle->owner.promote(), frameNumber); + deferTransactionUntil_legacy(handle->owner.promote(), frameNumber); } - // ---------------------------------------------------------------------------- // pageflip handling... // ---------------------------------------------------------------------------- @@ -1415,25 +1422,25 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { sp parent = getParent(); info.mParentName = (parent == nullptr ? std::string("none") : parent->getName().string()); info.mType = String8(getTypeId()); - info.mTransparentRegion = ds.activeTransparentRegion; + info.mTransparentRegion = ds.activeTransparentRegion_legacy; info.mVisibleRegion = visibleRegion; info.mSurfaceDamageRegion = surfaceDamageRegion; info.mLayerStack = getLayerStack(); - info.mX = ds.active.transform.tx(); - info.mY = ds.active.transform.ty(); + info.mX = ds.active_legacy.transform.tx(); + info.mY = ds.active_legacy.transform.ty(); info.mZ = ds.z; - info.mWidth = ds.active.w; - info.mHeight = ds.active.h; - info.mCrop = ds.crop; - info.mFinalCrop = ds.finalCrop; + info.mWidth = ds.active_legacy.w; + info.mHeight = ds.active_legacy.h; + info.mCrop = ds.crop_legacy; + info.mFinalCrop = ds.finalCrop_legacy; info.mColor = ds.color; info.mFlags = ds.flags; info.mPixelFormat = getPixelFormat(); info.mDataSpace = static_cast(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]; + info.mMatrix[0][0] = ds.active_legacy.transform[0][0]; + info.mMatrix[0][1] = ds.active_legacy.transform[0][1]; + info.mMatrix[1][0] = ds.active_legacy.transform[1][0]; + info.mMatrix[1][1] = ds.active_legacy.transform[1][1]; { sp buffer = mActiveBuffer; if (buffer != 0) { @@ -1882,14 +1889,14 @@ Transform Layer::getTransform() const { bufferHeight = p->getBE().compositionInfo.mBuffer->getWidth(); bufferWidth = p->getBE().compositionInfo.mBuffer->getHeight(); } - float sx = p->getDrawingState().active.w / static_cast(bufferWidth); - float sy = p->getDrawingState().active.h / static_cast(bufferHeight); + float sx = p->getDrawingState().active_legacy.w / static_cast(bufferWidth); + float sy = p->getDrawingState().active_legacy.h / static_cast(bufferHeight); Transform extraParentScaling; extraParentScaling.set(sx, 0, 0, sy); t = t * extraParentScaling; } } - return t * getDrawingState().active.transform; + return t * getDrawingState().active_legacy.transform; } half Layer::getAlpha() const { @@ -1918,7 +1925,7 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; const State& state = useDrawing ? mDrawingState : mCurrentState; - Transform requestedTransform = state.active.transform; + Transform requestedTransform = state.active_legacy.transform; Transform transform = getTransform(); layerInfo->set_id(sequence); @@ -1936,7 +1943,7 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) } } - LayerProtoHelper::writeToProto(state.activeTransparentRegion, + LayerProtoHelper::writeToProto(state.activeTransparentRegion_legacy, layerInfo->mutable_transparent_region()); LayerProtoHelper::writeToProto(visibleRegion, layerInfo->mutable_visible_region()); LayerProtoHelper::writeToProto(surfaceDamageRegion, layerInfo->mutable_damage_region()); @@ -1953,11 +1960,11 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) requestedPosition->set_y(requestedTransform.ty()); SizeProto* size = layerInfo->mutable_size(); - size->set_w(state.active.w); - size->set_h(state.active.h); + size->set_w(state.active_legacy.w); + size->set_h(state.active_legacy.h); - LayerProtoHelper::writeToProto(state.crop, layerInfo->mutable_crop()); - LayerProtoHelper::writeToProto(state.finalCrop, layerInfo->mutable_final_crop()); + LayerProtoHelper::writeToProto(state.crop_legacy, layerInfo->mutable_crop()); + LayerProtoHelper::writeToProto(state.finalCrop_legacy, layerInfo->mutable_final_crop()); layerInfo->set_is_opaque(isOpaque(state)); layerInfo->set_invalidate(contentDirty); @@ -1998,11 +2005,11 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) layerInfo->set_curr_frame(mCurrentFrameNumber); for (const auto& pendingState : mPendingStates) { - auto barrierLayer = pendingState.barrierLayer.promote(); + auto barrierLayer = pendingState.barrierLayer_legacy.promote(); if (barrierLayer != nullptr) { BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer(); barrierLayerProto->set_id(barrierLayer->sequence); - barrierLayerProto->set_frame_number(pendingState.frameNumber); + barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy); } } } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 94f086cafe..96ec84b269 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -111,8 +111,8 @@ public: }; struct State { - Geometry active; - Geometry requested; + Geometry active_legacy; + Geometry requested_legacy; int32_t z; // The identifier of the layer stack this layer belongs to. A layer can @@ -128,23 +128,23 @@ public: bool modified; // Crop is expressed in layer space coordinate. - Rect crop; - Rect requestedCrop; + Rect crop_legacy; + Rect requestedCrop_legacy; // finalCrop is expressed in display space coordinate. - Rect finalCrop; - Rect requestedFinalCrop; + Rect finalCrop_legacy; + Rect requestedFinalCrop_legacy; // If set, defers this state update until the identified Layer // receives a frame with the given frameNumber - wp barrierLayer; - uint64_t frameNumber; + wp barrierLayer_legacy; + uint64_t frameNumber_legacy; // the transparentRegion hint is a bit special, it's latched only // when we receive a buffer -- this is because it's "content" // dependent. - Region activeTransparentRegion; - Region requestedTransparentRegion; + Region activeTransparentRegion_legacy; + Region requestedTransparentRegion_legacy; int32_t appId; int32_t type; @@ -207,9 +207,9 @@ public: // space for top-level layers. bool setPosition(float x, float y, bool immediate); // Buffer space - bool setCrop(const Rect& crop, bool immediate); + bool setCrop_legacy(const Rect& crop, bool immediate); // Parent buffer space/display space - bool setFinalCrop(const Rect& crop, bool immediate); + bool setFinalCrop_legacy(const Rect& crop, bool immediate); // TODO(b/38182121): Could we eliminate the various latching modes by // using the layer hierarchy? @@ -223,8 +223,8 @@ public: bool setFlags(uint8_t flags, uint8_t mask); bool setLayerStack(uint32_t layerStack); uint32_t getLayerStack() const; - void deferTransactionUntil(const sp& barrierHandle, uint64_t frameNumber); - void deferTransactionUntil(const sp& barrierLayer, uint64_t frameNumber); + void deferTransactionUntil_legacy(const sp& barrierHandle, uint64_t frameNumber); + void deferTransactionUntil_legacy(const sp& barrierLayer, uint64_t frameNumber); bool setOverrideScalingMode(int32_t overrideScalingMode); void setInfo(int32_t type, int32_t appId); bool reparentChildren(const sp& layer); diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp index 381ea4aad3..fd0ca822c6 100644 --- a/services/surfaceflinger/LayerRejecter.cpp +++ b/services/surfaceflinger/LayerRejecter.cpp @@ -65,20 +65,21 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) int actualScalingMode = mOverrideScalingMode >= 0 ? mOverrideScalingMode : item.mScalingMode; bool isFixedSize = actualScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE; - if (mFront.active != mFront.requested) { - if (isFixedSize || (bufWidth == mFront.requested.w && bufHeight == mFront.requested.h)) { + if (mFront.active_legacy != mFront.requested_legacy) { + if (isFixedSize || + (bufWidth == mFront.requested_legacy.w && bufHeight == mFront.requested_legacy.h)) { // Here we pretend the transaction happened by updating the // current and drawing states. Drawing state is only accessed // in this thread, no need to have it locked - mFront.active = mFront.requested; + mFront.active_legacy = mFront.requested_legacy; // We also need to update the current state so that // we don't end-up overwriting the drawing state with // this stale current state during the next transaction // // NOTE: We don't need to hold the transaction lock here - // because State::active is only accessed from this thread. - mCurrent.active = mFront.active; + // because State::active_legacy is only accessed from this thread. + mCurrent.active_legacy = mFront.active_legacy; mCurrent.modified = true; // recompute visible region @@ -86,14 +87,14 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) mFreezeGeometryUpdates = false; - if (mFront.crop != mFront.requestedCrop) { - mFront.crop = mFront.requestedCrop; - mCurrent.crop = mFront.requestedCrop; + if (mFront.crop_legacy != mFront.requestedCrop_legacy) { + mFront.crop_legacy = mFront.requestedCrop_legacy; + mCurrent.crop_legacy = mFront.requestedCrop_legacy; mRecomputeVisibleRegions = true; } - if (mFront.finalCrop != mFront.requestedFinalCrop) { - mFront.finalCrop = mFront.requestedFinalCrop; - mCurrent.finalCrop = mFront.requestedFinalCrop; + if (mFront.finalCrop_legacy != mFront.requestedFinalCrop_legacy) { + mFront.finalCrop_legacy = mFront.requestedFinalCrop_legacy; + mCurrent.finalCrop_legacy = mFront.requestedFinalCrop_legacy; mRecomputeVisibleRegions = true; } } @@ -102,19 +103,20 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) "[%s] latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n" " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) " "}\n" - " requested={ wh={%4u,%4u} }}\n", - mName, bufWidth, bufHeight, item.mTransform, item.mScalingMode, mFront.active.w, - mFront.active.h, mFront.crop.left, mFront.crop.top, mFront.crop.right, - mFront.crop.bottom, mFront.crop.getWidth(), mFront.crop.getHeight(), - mFront.requested.w, mFront.requested.h); + " requested_legacy={ wh={%4u,%4u} }}\n", + mName, bufWidth, bufHeight, item.mTransform, item.mScalingMode, + mFront.active_legacy.w, mFront.active_legacy.h, mFront.crop_legacy.left, + mFront.crop_legacy.top, mFront.crop_legacy.right, mFront.crop_legacy.bottom, + mFront.crop_legacy.getWidth(), mFront.crop_legacy.getHeight(), + mFront.requested_legacy.w, mFront.requested_legacy.h); } if (!isFixedSize && !mStickyTransformSet) { - if (mFront.active.w != bufWidth || mFront.active.h != bufHeight) { + if (mFront.active_legacy.w != bufWidth || mFront.active_legacy.h != bufHeight) { // reject this buffer ALOGE("[%s] rejecting buffer: " - "bufWidth=%d, bufHeight=%d, front.active.{w=%d, h=%d}", - mName, bufWidth, bufHeight, mFront.active.w, mFront.active.h); + "bufWidth=%d, bufHeight=%d, front.active_legacy.{w=%d, h=%d}", + mName, bufWidth, bufHeight, mFront.active_legacy.w, mFront.active_legacy.h); return true; } } @@ -127,16 +129,17 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) // We latch the transparent region here, instead of above where we latch // the rest of the geometry because it is only content but not necessarily // resize dependent. - if (!mFront.activeTransparentRegion.isTriviallyEqual(mFront.requestedTransparentRegion)) { - mFront.activeTransparentRegion = mFront.requestedTransparentRegion; + if (!mFront.activeTransparentRegion_legacy.isTriviallyEqual( + mFront.requestedTransparentRegion_legacy)) { + mFront.activeTransparentRegion_legacy = mFront.requestedTransparentRegion_legacy; // We also need to update the current state so that // we don't end-up overwriting the drawing state with // this stale current state during the next transaction // // NOTE: We don't need to hold the transaction lock here - // because State::active is only accessed from this thread. - mCurrent.activeTransparentRegion = mFront.activeTransparentRegion; + // because State::active_legacy is only accessed from this thread. + mCurrent.activeTransparentRegion_legacy = mFront.activeTransparentRegion_legacy; // recompute visible region mRecomputeVisibleRegions = true; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 64520d0979..64f1eaf463 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2766,7 +2766,7 @@ void SurfaceFlinger::computeVisibleRegions(const sp& displa if (translucent) { if (tr.preserveRects()) { // transform the transparent region - transparentRegion = tr.transform(s.activeTransparentRegion); + transparentRegion = tr.transform(s.activeTransparentRegion_legacy); } else { // transformation too complex, can't do the // transparent region optimization. @@ -3400,7 +3400,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState // If we are deferring transaction, make sure to push the pending state, as otherwise the // pending state will also be deferred. - if (what & layer_state_t::eDeferTransaction) { + if (what & layer_state_t::eDeferTransaction_legacy) { layer->pushPendingState(); } @@ -3485,12 +3485,12 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState if (layer->setFlags(s.flags, s.mask)) flags |= eTraversalNeeded; } - if (what & layer_state_t::eCropChanged) { - if (layer->setCrop(s.crop, !geometryAppliesWithResize)) + if (what & layer_state_t::eCropChanged_legacy) { + if (layer->setCrop_legacy(s.crop_legacy, !geometryAppliesWithResize)) flags |= eTraversalNeeded; } - if (what & layer_state_t::eFinalCropChanged) { - if (layer->setFinalCrop(s.finalCrop, !geometryAppliesWithResize)) + if (what & layer_state_t::eFinalCropChanged_legacy) { + if (layer->setFinalCrop_legacy(s.finalCrop_legacy, !geometryAppliesWithResize)) flags |= eTraversalNeeded; } if (what & layer_state_t::eLayerStackChanged) { @@ -3512,15 +3512,15 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState flags |= eTransactionNeeded|eTraversalNeeded|eDisplayLayerStackChanged; } } - if (what & layer_state_t::eDeferTransaction) { - if (s.barrierHandle != nullptr) { - layer->deferTransactionUntil(s.barrierHandle, s.frameNumber); - } else if (s.barrierGbp != nullptr) { - const sp& gbp = s.barrierGbp; + if (what & layer_state_t::eDeferTransaction_legacy) { + if (s.barrierHandle_legacy != nullptr) { + layer->deferTransactionUntil_legacy(s.barrierHandle_legacy, s.frameNumber_legacy); + } else if (s.barrierGbp_legacy != nullptr) { + const sp& gbp = s.barrierGbp_legacy; if (authenticateSurfaceTextureLocked(gbp)) { const auto& otherLayer = (static_cast(gbp.get()))->getLayer(); - layer->deferTransactionUntil(otherLayer, s.frameNumber); + layer->deferTransactionUntil_legacy(otherLayer, s.frameNumber_legacy); } else { ALOGE("Attempt to defer transaction to to an" " unrecognized GraphicBufferProducer"); @@ -4864,10 +4864,10 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, const Transform& getTransform() const override { return mTransform; } Rect getBounds() const override { const Layer::State& layerState(mLayer->getDrawingState()); - return Rect(layerState.active.w, layerState.active.h); + return Rect(layerState.active_legacy.w, layerState.active_legacy.h); } - int getHeight() const override { return mLayer->getDrawingState().active.h; } - int getWidth() const override { return mLayer->getDrawingState().active.w; } + int getHeight() const override { return mLayer->getDrawingState().active_legacy.h; } + int getWidth() const override { return mLayer->getDrawingState().active_legacy.w; } bool isSecure() const override { return false; } bool needsFiltering() const override { return false; } Rect getSourceCrop() const override { @@ -4935,12 +4935,12 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, Rect crop(sourceCrop); if (sourceCrop.width() <= 0) { crop.left = 0; - crop.right = parent->getCurrentState().active.w; + crop.right = parent->getCurrentState().active_legacy.w; } if (sourceCrop.height() <= 0) { crop.top = 0; - crop.bottom = parent->getCurrentState().active.h; + crop.bottom = parent->getCurrentState().active_legacy.h; } int32_t reqWidth = crop.width() * frameScale; diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index e70506daac..c42213a28d 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -99,18 +99,20 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, transaction->set_animation(layer->mTransactionFlags & BnSurfaceComposer::eAnimation); const int32_t layerId(getLayerId(layer)); - addPositionLocked(transaction, layerId, layer->mCurrentState.active.transform.tx(), - layer->mCurrentState.active.transform.ty()); + addPositionLocked(transaction, layerId, layer->mCurrentState.active_legacy.transform.tx(), + layer->mCurrentState.active_legacy.transform.ty()); addDepthLocked(transaction, layerId, layer->mCurrentState.z); addAlphaLocked(transaction, layerId, layer->mCurrentState.color.a); - addTransparentRegionLocked(transaction, layerId, layer->mCurrentState.activeTransparentRegion); + addTransparentRegionLocked(transaction, layerId, + layer->mCurrentState.activeTransparentRegion_legacy); addLayerStackLocked(transaction, layerId, layer->mCurrentState.layerStack); - addCropLocked(transaction, layerId, layer->mCurrentState.crop); - if (layer->mCurrentState.barrierLayer != nullptr) { - addDeferTransactionLocked(transaction, layerId, layer->mCurrentState.barrierLayer.promote(), - layer->mCurrentState.frameNumber); + addCropLocked(transaction, layerId, layer->mCurrentState.crop_legacy); + if (layer->mCurrentState.barrierLayer_legacy != nullptr) { + addDeferTransactionLocked(transaction, layerId, + layer->mCurrentState.barrierLayer_legacy.promote(), + layer->mCurrentState.frameNumber_legacy); } - addFinalCropLocked(transaction, layerId, layer->mCurrentState.finalCrop); + addFinalCropLocked(transaction, layerId, layer->mCurrentState.finalCrop_legacy); addOverrideScalingModeLocked(transaction, layerId, layer->getEffectiveScalingMode()); addFlagsLocked(transaction, layerId, layer->mCurrentState.flags); } @@ -353,25 +355,26 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, if (state.what & layer_state_t::eLayerStackChanged) { addLayerStackLocked(transaction, layerId, state.layerStack); } - if (state.what & layer_state_t::eCropChanged) { - addCropLocked(transaction, layerId, state.crop); + if (state.what & layer_state_t::eCropChanged_legacy) { + addCropLocked(transaction, layerId, state.crop_legacy); } - if (state.what & layer_state_t::eDeferTransaction) { + if (state.what & layer_state_t::eDeferTransaction_legacy) { sp otherLayer = nullptr; - if (state.barrierHandle != nullptr) { - otherLayer = static_cast(state.barrierHandle.get())->owner.promote(); - } else if (state.barrierGbp != nullptr) { - auto const& gbp = state.barrierGbp; + if (state.barrierHandle_legacy != nullptr) { + otherLayer = + static_cast(state.barrierHandle_legacy.get())->owner.promote(); + } else if (state.barrierGbp_legacy != nullptr) { + auto const& gbp = state.barrierGbp_legacy; if (mFlinger->authenticateSurfaceTextureLocked(gbp)) { otherLayer = (static_cast(gbp.get()))->getLayer(); } else { ALOGE("Attempt to defer transaction to to an unrecognized GraphicBufferProducer"); } } - addDeferTransactionLocked(transaction, layerId, otherLayer, state.frameNumber); + addDeferTransactionLocked(transaction, layerId, otherLayer, state.frameNumber_legacy); } - if (state.what & layer_state_t::eFinalCropChanged) { - addFinalCropLocked(transaction, layerId, state.finalCrop); + if (state.what & layer_state_t::eFinalCropChanged_legacy) { + addFinalCropLocked(transaction, layerId, state.finalCrop_legacy); } if (state.what & layer_state_t::eOverrideScalingModeChanged) { addOverrideScalingModeLocked(transaction, layerId, state.overrideScalingMode); @@ -422,8 +425,8 @@ void SurfaceInterceptor::addSurfaceCreationLocked(Increment* increment, SurfaceCreation* creation(increment->mutable_surface_creation()); creation->set_id(getLayerId(layer)); creation->set_name(getLayerName(layer)); - creation->set_w(layer->mCurrentState.active.w); - creation->set_h(layer->mCurrentState.active.h); + creation->set_w(layer->mCurrentState.active_legacy.w); + creation->set_h(layer->mCurrentState.active_legacy.h); } void SurfaceInterceptor::addSurfaceDeletionLocked(Increment* increment, diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index 135d2afea2..8ac2c87b9e 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -320,11 +320,11 @@ void SurfaceInterceptorTest::layerUpdate(Transaction& t) { } void SurfaceInterceptorTest::cropUpdate(Transaction& t) { - t.setCrop(mBGSurfaceControl, CROP_UPDATE); + t.setCrop_legacy(mBGSurfaceControl, CROP_UPDATE); } void SurfaceInterceptorTest::finalCropUpdate(Transaction& t) { - t.setFinalCrop(mBGSurfaceControl, CROP_UPDATE); + t.setFinalCrop_legacy(mBGSurfaceControl, CROP_UPDATE); } void SurfaceInterceptorTest::matrixUpdate(Transaction& t) { @@ -357,7 +357,8 @@ void SurfaceInterceptorTest::secureFlagUpdate(Transaction& t) { } void SurfaceInterceptorTest::deferredTransactionUpdate(Transaction& t) { - t.deferTransactionUntil(mBGSurfaceControl, mBGSurfaceControl->getHandle(), DEFERRED_UPDATE); + t.deferTransactionUntil_legacy(mBGSurfaceControl, mBGSurfaceControl->getHandle(), + DEFERRED_UPDATE); } void SurfaceInterceptorTest::displayCreation(Transaction&) { diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 5108279043..2ce32b5967 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -1188,7 +1188,7 @@ TEST_F(LayerTransactionTest, SetCropBasic) { ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); const Rect crop(8, 8, 24, 24); - Transaction().setCrop(layer, crop).apply(); + Transaction().setCrop_legacy(layer, crop).apply(); auto shot = screenshot(); shot->expectColor(crop, Color::RED); shot->expectBorder(crop, Color::BLACK); @@ -1201,13 +1201,13 @@ TEST_F(LayerTransactionTest, SetCropEmpty) { { SCOPED_TRACE("empty rect"); - Transaction().setCrop(layer, Rect(8, 8, 8, 8)).apply(); + Transaction().setCrop_legacy(layer, Rect(8, 8, 8, 8)).apply(); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } { SCOPED_TRACE("negative rect"); - Transaction().setCrop(layer, Rect(8, 8, 0, 0)).apply(); + Transaction().setCrop_legacy(layer, Rect(8, 8, 0, 0)).apply(); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } } @@ -1217,7 +1217,7 @@ TEST_F(LayerTransactionTest, SetCropOutOfBounds) { ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); - Transaction().setCrop(layer, Rect(-128, -64, 128, 64)).apply(); + Transaction().setCrop_legacy(layer, Rect(-128, -64, 128, 64)).apply(); auto shot = screenshot(); shot->expectColor(Rect(0, 0, 32, 32), Color::RED); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); @@ -1230,7 +1230,7 @@ TEST_F(LayerTransactionTest, SetCropWithTranslation) { const Point position(32, 32); const Rect crop(8, 8, 24, 24); - Transaction().setPosition(layer, position.x, position.y).setCrop(layer, crop).apply(); + Transaction().setPosition(layer, position.x, position.y).setCrop_legacy(layer, crop).apply(); auto shot = screenshot(); shot->expectColor(crop + position, Color::RED); shot->expectBorder(crop + position, Color::BLACK); @@ -1244,7 +1244,7 @@ TEST_F(LayerTransactionTest, SetCropWithScale) { // crop is affected by matrix Transaction() .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f) - .setCrop(layer, Rect(8, 8, 24, 24)) + .setCrop_legacy(layer, Rect(8, 8, 24, 24)) .apply(); auto shot = screenshot(); shot->expectColor(Rect(16, 16, 48, 48), Color::RED); @@ -1256,8 +1256,8 @@ TEST_F(LayerTransactionTest, SetCropWithResize) { ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); - // setCrop is applied immediately by default, with or without resize pending - Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); + // setCrop_legacy is applied immediately by default, with or without resize pending + Transaction().setCrop_legacy(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); { SCOPED_TRACE("resize pending"); auto shot = screenshot(); @@ -1279,14 +1279,17 @@ TEST_F(LayerTransactionTest, SetCropWithNextResize) { ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); - // request setCrop to be applied with the next resize - Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setGeometryAppliesWithResize(layer).apply(); + // request setCrop_legacy to be applied with the next resize + Transaction() + .setCrop_legacy(layer, Rect(8, 8, 24, 24)) + .setGeometryAppliesWithResize(layer) + .apply(); { SCOPED_TRACE("waiting for next resize"); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } - Transaction().setCrop(layer, Rect(4, 4, 12, 12)).apply(); + Transaction().setCrop_legacy(layer, Rect(4, 4, 12, 12)).apply(); { SCOPED_TRACE("pending crop modified"); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); @@ -1313,9 +1316,9 @@ TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow) { ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); - // setCrop is not immediate even with SCALE_TO_WINDOW override + // setCrop_legacy is not immediate even with SCALE_TO_WINDOW override Transaction() - .setCrop(layer, Rect(4, 4, 12, 12)) + .setCrop_legacy(layer, Rect(4, 4, 12, 12)) .setSize(layer, 16, 16) .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) .setGeometryAppliesWithResize(layer) @@ -1346,7 +1349,7 @@ TEST_F(LayerTransactionTest, SetFinalCropBasic) { const Rect crop(8, 8, 24, 24); // same as in SetCropBasic - Transaction().setFinalCrop(layer, crop).apply(); + Transaction().setFinalCrop_legacy(layer, crop).apply(); auto shot = screenshot(); shot->expectColor(crop, Color::RED); shot->expectBorder(crop, Color::BLACK); @@ -1360,13 +1363,13 @@ TEST_F(LayerTransactionTest, SetFinalCropEmpty) { // same as in SetCropEmpty { SCOPED_TRACE("empty rect"); - Transaction().setFinalCrop(layer, Rect(8, 8, 8, 8)).apply(); + Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 8, 8)).apply(); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } { SCOPED_TRACE("negative rect"); - Transaction().setFinalCrop(layer, Rect(8, 8, 0, 0)).apply(); + Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 0, 0)).apply(); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } } @@ -1377,7 +1380,7 @@ TEST_F(LayerTransactionTest, SetFinalCropOutOfBounds) { ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); // same as in SetCropOutOfBounds - Transaction().setFinalCrop(layer, Rect(-128, -64, 128, 64)).apply(); + Transaction().setFinalCrop_legacy(layer, Rect(-128, -64, 128, 64)).apply(); auto shot = screenshot(); shot->expectColor(Rect(0, 0, 32, 32), Color::RED); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); @@ -1389,7 +1392,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithTranslation) { ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); // final crop is applied post-translation - Transaction().setPosition(layer, 16, 16).setFinalCrop(layer, Rect(8, 8, 24, 24)).apply(); + Transaction().setPosition(layer, 16, 16).setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)).apply(); auto shot = screenshot(); shot->expectColor(Rect(16, 16, 24, 24), Color::RED); shot->expectBorder(Rect(16, 16, 24, 24), Color::BLACK); @@ -1403,7 +1406,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithScale) { // final crop is not affected by matrix Transaction() .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f) - .setFinalCrop(layer, Rect(8, 8, 24, 24)) + .setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)) .apply(); auto shot = screenshot(); shot->expectColor(Rect(8, 8, 24, 24), Color::RED); @@ -1416,7 +1419,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithResize) { ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); // same as in SetCropWithResize - Transaction().setFinalCrop(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); + Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); { SCOPED_TRACE("resize pending"); auto shot = screenshot(); @@ -1440,7 +1443,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResize) { // same as in SetCropWithNextResize Transaction() - .setFinalCrop(layer, Rect(8, 8, 24, 24)) + .setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)) .setGeometryAppliesWithResize(layer) .apply(); { @@ -1448,7 +1451,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResize) { screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } - Transaction().setFinalCrop(layer, Rect(4, 4, 12, 12)).apply(); + Transaction().setFinalCrop_legacy(layer, Rect(4, 4, 12, 12)).apply(); { SCOPED_TRACE("pending final crop modified"); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); @@ -1477,7 +1480,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow) { // same as in SetCropWithNextResizeScaleToWindow Transaction() - .setFinalCrop(layer, Rect(4, 4, 12, 12)) + .setFinalCrop_legacy(layer, Rect(4, 4, 12, 12)) .setSize(layer, 16, 16) .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) .setGeometryAppliesWithResize(layer) @@ -1649,8 +1652,8 @@ protected: asTransaction([&](Transaction& t) { t.setSize(mFGSurfaceControl, 64, 64); t.setPosition(mFGSurfaceControl, 64, 64); - t.setCrop(mFGSurfaceControl, Rect(0, 0, 64, 64)); - t.setFinalCrop(mFGSurfaceControl, Rect(0, 0, -1, -1)); + t.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 64, 64)); + t.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, -1, -1)); }); EXPECT_INITIAL_STATE("After restoring initial state"); @@ -1686,7 +1689,7 @@ TEST_F(CropLatchingTest, FinalCropLatchingBufferOldSize) { // Normally the crop applies immediately even while a resize is pending. asTransaction([&](Transaction& t) { t.setSize(mFGSurfaceControl, 128, 128); - t.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + t.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); }); EXPECT_CROPPED_STATE("after setting crop (without geometryAppliesWithResize)"); @@ -1700,7 +1703,7 @@ TEST_F(CropLatchingTest, FinalCropLatchingBufferOldSize) { asTransaction([&](Transaction& t) { t.setSize(mFGSurfaceControl, 128, 128); t.setGeometryAppliesWithResize(mFGSurfaceControl); - t.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + t.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); }); EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)"); @@ -1729,14 +1732,14 @@ TEST_F(LayerUpdateTest, DeferredTransactionTest) { // set up two deferred transactions on different frames asTransaction([&](Transaction& t) { t.setAlpha(mFGSurfaceControl, 0.75); - t.deferTransactionUntil(mFGSurfaceControl, mSyncSurfaceControl->getHandle(), - mSyncSurfaceControl->getSurface()->getNextFrameNumber()); + t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl->getHandle(), + mSyncSurfaceControl->getSurface()->getNextFrameNumber()); }); asTransaction([&](Transaction& t) { t.setPosition(mFGSurfaceControl, 128, 128); - t.deferTransactionUntil(mFGSurfaceControl, mSyncSurfaceControl->getHandle(), - mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1); + t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl->getHandle(), + mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1); }); { @@ -1881,7 +1884,7 @@ TEST_F(ChildLayerTest, ChildLayerCropping) { t.show(mChild); t.setPosition(mChild, 0, 0); t.setPosition(mFGSurfaceControl, 0, 0); - t.setCrop(mFGSurfaceControl, Rect(0, 0, 5, 5)); + t.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5)); }); { @@ -1897,7 +1900,7 @@ TEST_F(ChildLayerTest, ChildLayerFinalCropping) { t.show(mChild); t.setPosition(mChild, 0, 0); t.setPosition(mFGSurfaceControl, 0, 0); - t.setFinalCrop(mFGSurfaceControl, Rect(0, 0, 5, 5)); + t.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5)); }); { @@ -2166,8 +2169,8 @@ TEST_F(ChildLayerTest, Bug36858924) { // Show the child layer in a deferred transaction asTransaction([&](Transaction& t) { - t.deferTransactionUntil(mChild, mFGSurfaceControl->getHandle(), - mFGSurfaceControl->getSurface()->getNextFrameNumber()); + t.deferTransactionUntil_legacy(mChild, mFGSurfaceControl->getHandle(), + mFGSurfaceControl->getSurface()->getNextFrameNumber()); t.show(mChild); }); @@ -2465,8 +2468,9 @@ TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentVisibility) { } TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentCrop) { - - SurfaceComposerClient::Transaction().setCrop(mFGSurfaceControl, Rect(0, 0, 1, 1)).apply(true); + SurfaceComposerClient::Transaction() + .setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 1, 1)) + .apply(true); // Even though the parent is cropped out we should still capture the child. verify(); diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 070bd51802..7fafab9302 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -624,7 +624,7 @@ TEST_F(TransactionTest, LayerCrop) { { TransactionScope ts(*sFakeComposer); Rect cropRect(16, 16, 32, 32); - ts.setCrop(mFGSurfaceControl, cropRect); + ts.setCrop_legacy(mFGSurfaceControl, cropRect); } ASSERT_EQ(2, sFakeComposer->getFrameCount()); @@ -639,7 +639,7 @@ TEST_F(TransactionTest, LayerFinalCrop) { { TransactionScope ts(*sFakeComposer); Rect cropRect(32, 32, 32 + 64, 32 + 64); - ts.setFinalCrop(mFGSurfaceControl, cropRect); + ts.setFinalCrop_legacy(mFGSurfaceControl, cropRect); } ASSERT_EQ(2, sFakeComposer->getFrameCount()); @@ -657,7 +657,7 @@ TEST_F(TransactionTest, LayerFinalCropEmpty) { { TransactionScope ts(*sFakeComposer); Rect cropRect(16, 16, 32, 32); - ts.setFinalCrop(mFGSurfaceControl, cropRect); + ts.setFinalCrop_legacy(mFGSurfaceControl, cropRect); } ASSERT_EQ(2, sFakeComposer->getFrameCount()); @@ -847,18 +847,16 @@ TEST_F(TransactionTest, DeferredTransaction) { { TransactionScope ts(*sFakeComposer); ts.setAlpha(mFGSurfaceControl, 0.75); - ts.deferTransactionUntil(mFGSurfaceControl, - syncSurfaceControl->getHandle(), - syncSurfaceControl->getSurface()->getNextFrameNumber()); + ts.deferTransactionUntil_legacy(mFGSurfaceControl, syncSurfaceControl->getHandle(), + syncSurfaceControl->getSurface()->getNextFrameNumber()); } EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); { TransactionScope ts(*sFakeComposer); ts.setPosition(mFGSurfaceControl, 128, 128); - ts.deferTransactionUntil(mFGSurfaceControl, - syncSurfaceControl->getHandle(), - syncSurfaceControl->getSurface()->getNextFrameNumber() + 1); + ts.deferTransactionUntil_legacy(mFGSurfaceControl, syncSurfaceControl->getHandle(), + syncSurfaceControl->getSurface()->getNextFrameNumber() + 1); } EXPECT_EQ(4, sFakeComposer->getFrameCount()); EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); @@ -981,7 +979,7 @@ TEST_F(ChildLayerTest, Cropping) { ts.show(mChild); ts.setPosition(mChild, 0, 0); ts.setPosition(mFGSurfaceControl, 0, 0); - ts.setCrop(mFGSurfaceControl, Rect(0, 0, 5, 5)); + ts.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5)); } // NOTE: The foreground surface would be occluded by the child // now, but is included in the stack because the child is @@ -1000,7 +998,7 @@ TEST_F(ChildLayerTest, FinalCropping) { ts.show(mChild); ts.setPosition(mChild, 0, 0); ts.setPosition(mFGSurfaceControl, 0, 0); - ts.setFinalCrop(mFGSurfaceControl, Rect(0, 0, 5, 5)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5)); } auto referenceFrame = mBaseFrame; referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 0 + 5, 0 + 5}; @@ -1238,8 +1236,8 @@ TEST_F(ChildLayerTest, Bug36858924) { // Show the child layer in a deferred transaction { TransactionScope ts(*sFakeComposer); - ts.deferTransactionUntil(mChild, mFGSurfaceControl->getHandle(), - mFGSurfaceControl->getSurface()->getNextFrameNumber()); + ts.deferTransactionUntil_legacy(mChild, mFGSurfaceControl->getHandle(), + mFGSurfaceControl->getSurface()->getNextFrameNumber()); ts.show(mChild); } @@ -1355,8 +1353,8 @@ protected: TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 64, 64); ts.setPosition(mFGSurfaceControl, 64, 64); - ts.setCrop(mFGSurfaceControl, Rect(0, 0, 64, 64)); - ts.setFinalCrop(mFGSurfaceControl, Rect(0, 0, -1, -1)); + ts.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 64, 64)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, -1, -1)); } }; @@ -1400,7 +1398,7 @@ TEST_F(LatchingTest, CropLatching) { { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); - ts.setCrop(mFGSurfaceControl, Rect(0, 0, 63, 63)); + ts.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 63, 63)); } auto referenceFrame1 = mBaseFrame; @@ -1414,7 +1412,7 @@ TEST_F(LatchingTest, CropLatching) { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setCrop(mFGSurfaceControl, Rect(0, 0, 63, 63)); + ts.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 63, 63)); } EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); @@ -1432,7 +1430,7 @@ TEST_F(LatchingTest, FinalCropLatching) { { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); - ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); } auto referenceFrame1 = mBaseFrame; @@ -1447,7 +1445,7 @@ TEST_F(LatchingTest, FinalCropLatching) { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); } EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); @@ -1468,7 +1466,7 @@ TEST_F(LatchingTest, FinalCropLatchingBufferOldSize) { { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); - ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); } auto referenceFrame1 = mBaseFrame; @@ -1487,7 +1485,7 @@ TEST_F(LatchingTest, FinalCropLatchingBufferOldSize) { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); } EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); @@ -1516,12 +1514,12 @@ TEST_F(LatchingTest, FinalCropLatchingRegressionForb37531386) { TransactionScope ts(*sFakeComposer); ts.setSize(mFGSurfaceControl, 128, 128); ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); } { TransactionScope ts(*sFakeComposer); - ts.setFinalCrop(mFGSurfaceControl, Rect(0, 0, -1, -1)); + ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, -1, -1)); } EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); -- cgit v1.2.3-59-g8ed1b From 61c58627dd748baa699bab62e80a7972f2030f60 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Wed, 18 Jul 2018 10:12:20 -0700 Subject: blast: BufferStateLayer Adds the initial foundation for supporting buffers on transactions as well as the other metadata that had been passed over BufferQueue. Bug: 80477568 Test: Transaction_test.cpp Change-Id: I61e44462c66c1a912adbabf62015e66bde44c216 --- libs/gui/LayerState.cpp | 85 ++ libs/gui/SurfaceComposerClient.cpp | 121 +++ libs/gui/include/gui/ISurfaceComposerClient.h | 3 +- libs/gui/include/gui/LayerState.h | 33 +- libs/gui/include/gui/SurfaceComposerClient.h | 14 + services/surfaceflinger/Android.bp | 1 + services/surfaceflinger/BufferLayer.cpp | 19 +- services/surfaceflinger/BufferLayer.h | 9 +- services/surfaceflinger/BufferQueueLayer.cpp | 4 +- services/surfaceflinger/BufferQueueLayer.h | 4 +- services/surfaceflinger/BufferStateLayer.cpp | 545 ++++++++++ services/surfaceflinger/BufferStateLayer.h | 142 +++ services/surfaceflinger/ColorLayer.cpp | 4 +- services/surfaceflinger/ColorLayer.h | 4 +- services/surfaceflinger/ContainerLayer.cpp | 4 +- services/surfaceflinger/ContainerLayer.h | 4 +- services/surfaceflinger/Layer.cpp | 184 ++-- services/surfaceflinger/Layer.h | 103 +- services/surfaceflinger/LayerBE.h | 1 + services/surfaceflinger/LayerRejecter.cpp | 3 +- services/surfaceflinger/SurfaceFlinger.cpp | 61 +- services/surfaceflinger/SurfaceFlinger.h | 5 + services/surfaceflinger/SurfaceInterceptor.cpp | 1 + services/surfaceflinger/tests/Transaction_test.cpp | 1038 ++++++++++++++++---- 24 files changed, 2071 insertions(+), 321 deletions(-) create mode 100644 services/surfaceflinger/BufferStateLayer.cpp create mode 100644 services/surfaceflinger/BufferStateLayer.h (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 0414a486e6..931c446275 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -50,6 +50,32 @@ status_t layer_state_t::write(Parcel& output) const output.writeFloat(color.g); output.writeFloat(color.b); output.write(transparentRegion); + output.writeUint32(transform); + output.writeBool(transformToDisplayInverse); + output.write(crop); + if (buffer) { + output.writeBool(true); + output.write(*buffer); + } else { + output.writeBool(false); + } + if (acquireFence) { + output.writeBool(true); + output.write(*acquireFence); + } else { + output.writeBool(false); + } + output.writeUint32(static_cast(dataspace)); + output.write(hdrMetadata); + output.write(surfaceDamageRegion); + output.writeInt32(api); + if (sidebandStream) { + output.writeBool(true); + output.writeNativeHandle(sidebandStream->handle()); + } else { + output.writeBool(false); + } + return NO_ERROR; } @@ -85,6 +111,25 @@ status_t layer_state_t::read(const Parcel& input) color.g = input.readFloat(); color.b = input.readFloat(); input.read(transparentRegion); + transform = input.readUint32(); + transformToDisplayInverse = input.readBool(); + input.read(crop); + buffer = new GraphicBuffer(); + if (input.readBool()) { + input.read(*buffer); + } + acquireFence = new Fence(); + if (input.readBool()) { + input.read(*acquireFence); + } + dataspace = static_cast(input.readUint32()); + input.read(hdrMetadata); + input.read(surfaceDamageRegion); + api = input.readInt32(); + if (input.readBool()) { + sidebandStream = NativeHandle::create(input.readNativeHandle(), true); + } + return NO_ERROR; } @@ -233,6 +278,46 @@ void layer_state_t::merge(const layer_state_t& other) { if (other.what & eDestroySurface) { what |= eDestroySurface; } + if (other.what & eTransformChanged) { + what |= eTransformChanged; + transform = other.transform; + } + if (other.what & eTransformToDisplayInverseChanged) { + what |= eTransformToDisplayInverseChanged; + transformToDisplayInverse = other.transformToDisplayInverse; + } + if (other.what & eCropChanged) { + what |= eCropChanged; + crop = other.crop; + } + if (other.what & eBufferChanged) { + what |= eBufferChanged; + buffer = other.buffer; + } + if (other.what & eAcquireFenceChanged) { + what |= eAcquireFenceChanged; + acquireFence = other.acquireFence; + } + if (other.what & eDataspaceChanged) { + what |= eDataspaceChanged; + dataspace = other.dataspace; + } + if (other.what & eHdrMetadataChanged) { + what |= eHdrMetadataChanged; + hdrMetadata = other.hdrMetadata; + } + if (other.what & eSurfaceDamageRegionChanged) { + what |= eSurfaceDamageRegionChanged; + surfaceDamageRegion = other.surfaceDamageRegion; + } + if (other.what & eApiChanged) { + what |= eApiChanged; + api = other.api; + } + if (other.what & eSidebandStreamChanged) { + what |= eSidebandStreamChanged; + sidebandStream = other.sidebandStream; + } } }; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 3ff0ec20ea..17cff546e0 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -437,6 +437,127 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColor return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTransform( + const sp& sc, uint32_t transform) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eTransformChanged; + s->transform = transform; + return *this; +} + +SurfaceComposerClient::Transaction& +SurfaceComposerClient::Transaction::setTransformToDisplayInverse(const sp& sc, + bool transformToDisplayInverse) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eTransformToDisplayInverseChanged; + s->transformToDisplayInverse = transformToDisplayInverse; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCrop( + const sp& sc, const Rect& crop) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eCropChanged; + s->crop = crop; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer( + const sp& sc, const sp& buffer) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eBufferChanged; + s->buffer = buffer; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAcquireFence( + const sp& sc, const sp& fence) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eAcquireFenceChanged; + s->acquireFence = fence; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDataspace( + const sp& sc, ui::Dataspace dataspace) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eDataspaceChanged; + s->dataspace = dataspace; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setHdrMetadata( + const sp& sc, const HdrMetadata& hdrMetadata) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eHdrMetadataChanged; + s->hdrMetadata = hdrMetadata; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSurfaceDamageRegion( + const sp& sc, const Region& surfaceDamageRegion) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eSurfaceDamageRegionChanged; + s->surfaceDamageRegion = surfaceDamageRegion; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setApi( + const sp& sc, int32_t api) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eApiChanged; + s->api = api; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSidebandStream( + const sp& sc, const sp& sidebandStream) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eSidebandStreamChanged; + s->sidebandStream = sidebandStream; + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachChildren( const sp& sc) { layer_state_t* s = getLayerState(sc); diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h index 8dfc99a4b7..11261c307c 100644 --- a/libs/gui/include/gui/ISurfaceComposerClient.h +++ b/libs/gui/include/gui/ISurfaceComposerClient.h @@ -40,8 +40,9 @@ public: eProtectedByDRM = 0x00001000, eCursorWindow = 0x00002000, - eFXSurfaceNormal = 0x00000000, + eFXSurfaceBufferQueue = 0x00000000, eFXSurfaceColor = 0x00020000, + eFXSurfaceBufferState = 0x00040000, eFXSurfaceMask = 0x000F0000, }; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index b88b7fe118..098179864a 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -61,7 +62,17 @@ struct layer_state_t { eRelativeLayerChanged = 0x00008000, eReparent = 0x00010000, eColorChanged = 0x00020000, - eDestroySurface = 0x00040000 + eDestroySurface = 0x00040000, + eTransformChanged = 0x00100000, + eTransformToDisplayInverseChanged = 0x00200000, + eCropChanged = 0x00400000, + eBufferChanged = 0x00800000, + eAcquireFenceChanged = 0x01000000, + eDataspaceChanged = 0x02000000, + eHdrMetadataChanged = 0x04000000, + eSurfaceDamageRegionChanged = 0x08000000, + eApiChanged = 0x10000000, + eSidebandStreamChanged = 0x20000000, }; layer_state_t() @@ -79,9 +90,16 @@ struct layer_state_t { crop_legacy(Rect::INVALID_RECT), finalCrop_legacy(Rect::INVALID_RECT), frameNumber_legacy(0), - overrideScalingMode(-1) { + overrideScalingMode(-1), + transform(0), + transformToDisplayInverse(false), + crop(Rect::INVALID_RECT), + dataspace(ui::Dataspace::UNKNOWN), + surfaceDamageRegion(), + api(-1) { matrix.dsdx = matrix.dtdy = 1.0f; matrix.dsdy = matrix.dtdx = 0.0f; + hdrMetadata.validTypes = 0; } void merge(const layer_state_t& other); @@ -124,6 +142,17 @@ struct layer_state_t { // non POD must be last. see write/read Region transparentRegion; + + uint32_t transform; + bool transformToDisplayInverse; + Rect crop; + sp buffer; + sp acquireFence; + ui::Dataspace dataspace; + HdrMetadata hdrMetadata; + Region surfaceDamageRegion; + int32_t api; + sp sidebandStream; }; struct ComposerState { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 278a642c91..4907866d0f 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -227,6 +227,20 @@ public: Transaction& setColor(const sp& sc, const half3& color); + Transaction& setTransform(const sp& sc, uint32_t transform); + Transaction& setTransformToDisplayInverse(const sp& sc, + bool transformToDisplayInverse); + Transaction& setCrop(const sp& sc, const Rect& crop); + Transaction& setBuffer(const sp& sc, const sp& buffer); + Transaction& setAcquireFence(const sp& sc, const sp& fence); + Transaction& setDataspace(const sp& sc, ui::Dataspace dataspace); + Transaction& setHdrMetadata(const sp& sc, const HdrMetadata& hdrMetadata); + Transaction& setSurfaceDamageRegion(const sp& sc, + const Region& surfaceDamageRegion); + Transaction& setApi(const sp& sc, int32_t api); + Transaction& setSidebandStream(const sp& sc, + const sp& sidebandStream); + // Detaches all child surfaces (and their children recursively) // from their SurfaceControl. // The child SurfaceControls will not throw exceptions or return errors, diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 0be1fd7d93..3fa1311ce9 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -92,6 +92,7 @@ filegroup { "BufferLayer.cpp", "BufferLayerConsumer.cpp", "BufferQueueLayer.cpp", + "BufferStateLayer.cpp", "Client.cpp", "ColorLayer.cpp", "ContainerLayer.cpp", diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 64842450fa..e7246665dd 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -136,7 +136,7 @@ static constexpr mat4 inverseOrientation(uint32_t transform) { * onDraw will draw the current layer onto the presentable buffer */ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform) const { + bool useIdentityTransform) { ATRACE_CALL(); CompositionInfo& compositionInfo = getBE().compositionInfo; @@ -232,7 +232,7 @@ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, engine.disableTexturing(); } -void BufferLayer::drawNow(const RenderArea& renderArea, bool useIdentityTransform) const { +void BufferLayer::drawNow(const RenderArea& renderArea, bool useIdentityTransform) { CompositionInfo& compositionInfo = getBE().compositionInfo; auto& engine(mFlinger->getRenderEngine()); @@ -518,7 +518,7 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime // FIXME: postedRegion should be dirty & bounds // transform the dirty region to window-manager space - return getTransform().transform(Region(Rect(s.active_legacy.w, s.active_legacy.h))); + return getTransform().transform(Region(Rect(getActiveWidth(s), getActiveHeight(s)))); } // transaction @@ -641,9 +641,10 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT Transform t = getTransform(); Rect win = bounds; - if (!s.finalCrop_legacy.isEmpty()) { + Rect finalCrop = getFinalCrop(s); + if (!finalCrop.isEmpty()) { win = t.transform(win); - if (!win.intersect(s.finalCrop_legacy, &win)) { + if (!win.intersect(finalCrop, &win)) { win.clear(); } win = t.inverse().transform(win); @@ -652,10 +653,10 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT } } - float left = float(win.left) / float(s.active_legacy.w); - float top = float(win.top) / float(s.active_legacy.h); - float right = float(win.right) / float(s.active_legacy.w); - float bottom = float(win.bottom) / float(s.active_legacy.h); + float left = float(win.left) / float(getActiveWidth(s)); + float top = float(win.top) / float(getActiveHeight(s)); + float right = float(win.right) / float(getActiveWidth(s)); + float bottom = float(win.bottom) / float(getActiveHeight(s)); // TODO: we probably want to generate the texture coords with the mesh // here we assume that we only have 4 vertices diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 6ffcff4a2a..13f4e83b44 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -78,8 +78,8 @@ public: // onDraw - draws the surface. void onDraw(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform) const override; - void drawNow(const RenderArea& renderArea, bool useIdentityTransform) const; + bool useIdentityTransform) override; + void drawNow(const RenderArea& renderArea, bool useIdentityTransform); bool isHdrY410() const override; @@ -102,7 +102,6 @@ public: bool hasReadyFrame() const override; -private: // Returns the current scaling mode, unless mOverrideScalingMode // is set, in which case, it returns mOverrideScalingMode uint32_t getEffectiveScalingMode() const override; @@ -117,7 +116,7 @@ private: virtual nsecs_t getDesiredPresentTime() = 0; virtual std::shared_ptr getCurrentFenceTime() const = 0; - virtual void getDrawingTransformMatrix(float matrix[16]) const = 0; + virtual void getDrawingTransformMatrix(float *matrix) = 0; virtual uint32_t getDrawingTransform() const = 0; virtual ui::Dataspace getDrawingDataSpace() const = 0; virtual Rect getDrawingCrop() const = 0; @@ -136,7 +135,7 @@ private: virtual bool hasDrawingBuffer() const = 0; - virtual void setFilteringEnabled(bool enabled) const = 0; + virtual void setFilteringEnabled(bool enabled) = 0; virtual status_t bindTextureImage() const = 0; virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) = 0; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 1bf9cf275b..0913de419e 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -152,7 +152,7 @@ std::shared_ptr BufferQueueLayer::getCurrentFenceTime() const { return mConsumer->getCurrentFenceTime(); } -void BufferQueueLayer::getDrawingTransformMatrix(float matrix[16]) const { +void BufferQueueLayer::getDrawingTransformMatrix(float *matrix) { return mConsumer->getTransformMatrix(matrix); } @@ -228,7 +228,7 @@ bool BufferQueueLayer::hasDrawingBuffer() const { return mQueuedFrames > 0; } -void BufferQueueLayer::setFilteringEnabled(bool enabled) const { +void BufferQueueLayer::setFilteringEnabled(bool enabled) { return mConsumer->setFilteringEnabled(enabled); } diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 7454e2058a..579ed81f7e 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -68,7 +68,7 @@ private: nsecs_t getDesiredPresentTime() override; std::shared_ptr getCurrentFenceTime() const override; - void getDrawingTransformMatrix(float matrix[16]) const override; + void getDrawingTransformMatrix(float *matrix) override; uint32_t getDrawingTransform() const override; ui::Dataspace getDrawingDataSpace() const override; Rect getDrawingCrop() const override; @@ -87,7 +87,7 @@ private: bool hasDrawingBuffer() const override; - void setFilteringEnabled(bool enabled) const override; + void setFilteringEnabled(bool enabled) override; status_t bindTextureImage() const override; status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp new file mode 100644 index 0000000000..2e411f1ab8 --- /dev/null +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -0,0 +1,545 @@ +/* + * 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 "BufferStateLayer" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "BufferStateLayer.h" +#include "RenderEngine/Image.h" +#include "clz.h" + +#include + +namespace android { + +static const std::array IDENTITY_MATRIX{1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1}; + +BufferStateLayer::BufferStateLayer(SurfaceFlinger* flinger, const sp& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags) + : BufferLayer(flinger, client, name, w, h, flags), + mSidebandStreamChanged(false), + mFrameNumber(0) { + mTransformMatrix = IDENTITY_MATRIX; +} + +// ----------------------------------------------------------------------- +// Interface implementation for Layer +// ----------------------------------------------------------------------- +void BufferStateLayer::onLayerDisplayed(const sp& /*releaseFence*/) { + // TODO(marissaw): send the release fence back to buffer owner + return; +} + +void BufferStateLayer::setTransformHint(uint32_t /*orientation*/) const { + // TODO(marissaw): send the transform hint to buffer owner + return; +} + +void BufferStateLayer::releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) { + // TODO(marissaw): use this to signal the buffer owner + return; +} + +bool BufferStateLayer::shouldPresentNow(const DispSync& /*dispSync*/) const { + if (getSidebandStreamChanged() || getAutoRefresh()) { + return true; + } + + return hasDrawingBuffer(); +} + +bool BufferStateLayer::getTransformToDisplayInverse() const { + return mCurrentState.transformToDisplayInverse; +} + +void BufferStateLayer::pushPendingState() { + if (!mCurrentState.modified) { + return; + } + mPendingStates.push_back(mCurrentState); + ATRACE_INT(mTransactionName.string(), mPendingStates.size()); +} + +bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) { + const bool stateUpdateAvailable = !mPendingStates.empty(); + while (!mPendingStates.empty()) { + popPendingState(stateToCommit); + } + mCurrentState.modified = false; + return stateUpdateAvailable; +} + +Rect BufferStateLayer::getCrop(const Layer::State& s) const { + return (getEffectiveScalingMode() == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) + ? GLConsumer::scaleDownCrop(s.crop, s.active.w, s.active.h) + : s.crop; +} + +bool BufferStateLayer::setTransform(uint32_t transform) { + if (mCurrentState.transform == transform) return false; + mCurrentState.sequence++; + mCurrentState.transform = transform; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setTransformToDisplayInverse(bool transformToDisplayInverse) { + if (mCurrentState.transformToDisplayInverse == transformToDisplayInverse) return false; + mCurrentState.sequence++; + mCurrentState.transformToDisplayInverse = transformToDisplayInverse; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setCrop(const Rect& crop) { + if (mCurrentState.crop == crop) return false; + mCurrentState.sequence++; + mCurrentState.crop = crop; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setBuffer(sp buffer) { + mCurrentState.sequence++; + mCurrentState.buffer = buffer; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setAcquireFence(const sp& fence) { + mCurrentState.acquireFence = fence; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setDataspace(ui::Dataspace dataspace) { + if (mCurrentState.dataspace == dataspace) return false; + mCurrentState.sequence++; + mCurrentState.dataspace = dataspace; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setHdrMetadata(const HdrMetadata& hdrMetadata) { + if (mCurrentState.hdrMetadata == hdrMetadata) return false; + mCurrentState.sequence++; + mCurrentState.hdrMetadata = hdrMetadata; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setSurfaceDamageRegion(const Region& surfaceDamage) { + mCurrentState.sequence++; + mCurrentState.surfaceDamageRegion = surfaceDamage; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setApi(int32_t api) { + if (mCurrentState.api == api) return false; + mCurrentState.sequence++; + mCurrentState.api = api; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setSidebandStream(const sp& sidebandStream) { + if (mCurrentState.sidebandStream == sidebandStream) return false; + mCurrentState.sequence++; + mCurrentState.sidebandStream = sidebandStream; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + + if (!mSidebandStreamChanged.exchange(true)) { + // mSidebandStreamChanged was false + mFlinger->signalLayerUpdate(); + } + return true; +} + +bool BufferStateLayer::setSize(uint32_t w, uint32_t h) { + if (mCurrentState.active.w == w && mCurrentState.active.h == h) return false; + mCurrentState.active.w = w; + mCurrentState.active.h = h; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setPosition(float x, float y, bool /*immediate*/) { + if (mCurrentState.active.transform.tx() == x && mCurrentState.active.transform.ty() == y) + return false; + + mCurrentState.active.transform.set(x, y); + + mCurrentState.sequence++; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) { + mCurrentState.transparentRegionHint = transparent; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool BufferStateLayer::setMatrix(const layer_state_t::matrix22_t& matrix, + bool allowNonRectPreservingTransforms) { + Transform t; + t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); + + if (!allowNonRectPreservingTransforms && !t.preserveRects()) { + ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER ignored"); + return false; + } + + mCurrentState.sequence++; + mCurrentState.active.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} +// ----------------------------------------------------------------------- + +// ----------------------------------------------------------------------- +// Interface implementation for BufferLayer +// ----------------------------------------------------------------------- +bool BufferStateLayer::fenceHasSignaled() const { + if (latchUnsignaledBuffers()) { + return true; + } + + return getDrawingState().acquireFence->getStatus() == Fence::Status::Signaled; +} + +nsecs_t BufferStateLayer::getDesiredPresentTime() { + // TODO(marissaw): support an equivalent to desiredPresentTime for timestats metrics + return 0; +} + +std::shared_ptr BufferStateLayer::getCurrentFenceTime() const { + return std::make_shared(getDrawingState().acquireFence); +} + +void BufferStateLayer::getDrawingTransformMatrix(float *matrix) { + std::copy(std::begin(mTransformMatrix), std::end(mTransformMatrix), matrix); +} + +uint32_t BufferStateLayer::getDrawingTransform() const { + return getDrawingState().transform; +} + +ui::Dataspace BufferStateLayer::getDrawingDataSpace() const { + return getDrawingState().dataspace; +} + +Rect BufferStateLayer::getDrawingCrop() const { + return Rect::INVALID_RECT; +} + +uint32_t BufferStateLayer::getDrawingScalingMode() const { + return NATIVE_WINDOW_SCALING_MODE_FREEZE; +} + +Region BufferStateLayer::getDrawingSurfaceDamage() const { + return getDrawingState().surfaceDamageRegion; +} + +const HdrMetadata& BufferStateLayer::getDrawingHdrMetadata() const { + return getDrawingState().hdrMetadata; +} + +int BufferStateLayer::getDrawingApi() const { + return getDrawingState().api; +} + +PixelFormat BufferStateLayer::getPixelFormat() const { + return mActiveBuffer->format; +} + +uint64_t BufferStateLayer::getFrameNumber() const { + return mFrameNumber; +} + +bool BufferStateLayer::getAutoRefresh() const { + // TODO(marissaw): support shared buffer mode + return false; +} + +bool BufferStateLayer::getSidebandStreamChanged() const { + return mSidebandStreamChanged.load(); +} + +std::optional BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) { + if (mSidebandStreamChanged.exchange(false)) { + const State& s(getDrawingState()); + // mSidebandStreamChanged was true + // replicated in LayerBE until FE/BE is ready to be synchronized + getBE().compositionInfo.hwc.sidebandStream = s.sidebandStream; + if (getBE().compositionInfo.hwc.sidebandStream != nullptr) { + setTransactionFlags(eTransactionNeeded); + mFlinger->setTransactionFlags(eTraversalNeeded); + } + recomputeVisibleRegions = true; + + return getTransform().transform(Region(Rect(s.active.w, s.active.h))); + } + return {}; +} + +bool BufferStateLayer::hasDrawingBuffer() const { + return getDrawingState().buffer != nullptr; +} + +void BufferStateLayer::setFilteringEnabled(bool enabled) { + GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mActiveBuffer, mCurrentCrop, + mCurrentTransform, enabled); +} + +status_t BufferStateLayer::bindTextureImage() const { + const State& s(getDrawingState()); + auto& engine(mFlinger->getRenderEngine()); + + if (!engine.isCurrent()) { + ALOGE("RenderEngine is not current"); + return INVALID_OPERATION; + } + + engine.checkErrors(); + + if (!mTextureImage) { + ALOGE("no currently-bound texture"); + engine.bindExternalTextureImage(mTextureName, *engine.createImage()); + return NO_INIT; + } + + bool created = + mTextureImage->setNativeWindowBuffer(s.buffer->getNativeBuffer(), + s.buffer->getUsage() & GRALLOC_USAGE_PROTECTED); + if (!created) { + ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d", + s.buffer->getWidth(), s.buffer->getHeight(), s.buffer->getStride(), + s.buffer->getUsage(), s.buffer->getPixelFormat()); + engine.bindExternalTextureImage(mTextureName, *engine.createImage()); + return NO_INIT; + } + + engine.bindExternalTextureImage(mTextureName, *mTextureImage); + + // Wait for the new buffer to be ready. + if (s.acquireFence->isValid()) { + if (SyncFeatures::getInstance().useWaitSync()) { + base::unique_fd fenceFd(s.acquireFence->dup()); + if (fenceFd == -1) { + ALOGE("error dup'ing fence fd: %d", errno); + return -errno; + } + if (!engine.waitFence(std::move(fenceFd))) { + ALOGE("failed to wait on fence fd"); + return UNKNOWN_ERROR; + } + } else { + status_t err = s.acquireFence->waitForever("BufferStateLayer::bindTextureImage"); + if (err != NO_ERROR) { + ALOGE("error waiting for fence: %d", err); + return err; + } + } + } + + return NO_ERROR; +} + +status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime) { + const State& s(getDrawingState()); + + if (!s.buffer) { + return NO_ERROR; + } + + auto& engine(mFlinger->getRenderEngine()); + if (!engine.isCurrent()) { + ALOGE("RenderEngine is not current"); + return INVALID_OPERATION; + } + engine.checkErrors(); + + // TODO(marissaw): once buffers are cached, don't create a new image everytime + mTextureImage = engine.createImage(); + + // Reject if the layer is invalid + uint32_t bufferWidth = s.buffer->width; + uint32_t bufferHeight = s.buffer->height; + + if (s.transform & Transform::ROT_90) { + swap(bufferWidth, bufferHeight); + } + + if (s.transformToDisplayInverse) { + uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); + if (invTransform & Transform::ROT_90) { + swap(bufferWidth, bufferHeight); + } + } + + if (mOverrideScalingMode == NATIVE_WINDOW_SCALING_MODE_FREEZE && + (s.active.w != bufferWidth || s.active.h != bufferHeight)) { + ALOGE("[%s] rejecting buffer: " + "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}", + mName.string(), bufferWidth, bufferHeight, s.active.w, s.active.h); + mTimeStats.removeTimeRecord(getName().c_str(), getFrameNumber()); + return BAD_VALUE; + } + + // Handle sync fences + if (SyncFeatures::getInstance().useNativeFenceSync()) { + base::unique_fd fenceFd = engine.flush(); + if (fenceFd == -1) { + ALOGE("failed to flush RenderEngine"); + mTimeStats.clearLayerRecord(getName().c_str()); + return UNKNOWN_ERROR; + } + + sp fence(new Fence(std::move(fenceFd))); + + // Check status of fences first because merging is expensive. + // Merging an invalid fence with any other fence results in an + // invalid fence. + auto currentStatus = s.acquireFence->getStatus(); + if (currentStatus == Fence::Status::Invalid) { + ALOGE("Existing fence has invalid state"); + mTimeStats.clearLayerRecord(getName().c_str()); + return BAD_VALUE; + } + + auto incomingStatus = fence->getStatus(); + if (incomingStatus == Fence::Status::Invalid) { + ALOGE("New fence has invalid state"); + mDrawingState.acquireFence = fence; + mTimeStats.clearLayerRecord(getName().c_str()); + return BAD_VALUE; + } + + // If both fences are signaled or both are unsignaled, we need to merge + // them to get an accurate timestamp. + if (currentStatus == incomingStatus) { + char fenceName[32] = {}; + snprintf(fenceName, 32, "%.28s:%d", mName.string(), mFrameNumber); + sp mergedFence = Fence::merge(fenceName, mDrawingState.acquireFence, fence); + if (!mergedFence.get()) { + ALOGE("failed to merge release fences"); + // synchronization is broken, the best we can do is hope fences + // signal in order so the new fence will act like a union + mDrawingState.acquireFence = fence; + mTimeStats.clearLayerRecord(getName().c_str()); + return BAD_VALUE; + } + mDrawingState.acquireFence = mergedFence; + } else if (incomingStatus == Fence::Status::Unsignaled) { + // If one fence has signaled and the other hasn't, the unsignaled + // fence will approximately correspond with the correct timestamp. + // There's a small race if both fences signal at about the same time + // and their statuses are retrieved with unfortunate timing. However, + // by this point, they will have both signaled and only the timestamp + // will be slightly off; any dependencies after this point will + // already have been met. + mDrawingState.acquireFence = fence; + } + } else { + // Bind the new buffer to the GL texture. + // + // Older devices require the "implicit" synchronization provided + // by glEGLImageTargetTexture2DOES, which this method calls. Newer + // devices will either call this in Layer::onDraw, or (if it's not + // a GL-composited layer) not at all. + status_t err = bindTextureImage(); + if (err != NO_ERROR) { + mTimeStats.clearLayerRecord(getName().c_str()); + return BAD_VALUE; + } + } + + // TODO(marissaw): properly support mTimeStats + const std::string layerName(getName().c_str()); + mTimeStats.setPostTime(getName().c_str(), getFrameNumber(), latchTime); + mTimeStats.setAcquireFence(layerName, getFrameNumber(), getCurrentFenceTime()); + mTimeStats.setLatchTime(layerName, getFrameNumber(), latchTime); + + return NO_ERROR; +} + +status_t BufferStateLayer::updateActiveBuffer() { + const State& s(getDrawingState()); + + if (s.buffer == nullptr) { + return BAD_VALUE; + } + + mActiveBuffer = s.buffer; + getBE().compositionInfo.mBuffer = mActiveBuffer; + getBE().compositionInfo.mBufferSlot = 0; + + return NO_ERROR; +} + +status_t BufferStateLayer::updateFrameNumber(nsecs_t /*latchTime*/) { + // TODO(marissaw): support frame history events + mCurrentFrameNumber = mFrameNumber; + return NO_ERROR; +} + +void BufferStateLayer::setHwcLayerBuffer(const sp& display) { + const auto displayId = display->getId(); + auto& hwcInfo = getBE().mHwcLayers[displayId]; + auto& hwcLayer = hwcInfo.layer; + + const State& s(getDrawingState()); + + // TODO(marissaw): support more than one slot + uint32_t hwcSlot = 0; + + auto error = hwcLayer->setBuffer(hwcSlot, s.buffer, s.acquireFence); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), + s.buffer->handle, to_string(error).c_str(), static_cast(error)); + } + + mFrameNumber++; +} + +void BufferStateLayer::onFirstRef() { + if (const auto display = mFlinger->getDefaultDisplayDevice()) { + updateTransformHint(display); + } +} + +} // namespace android diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h new file mode 100644 index 0000000000..4d7396ef81 --- /dev/null +++ b/services/surfaceflinger/BufferStateLayer.h @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2018 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 "RenderEngine/Image.h" +#include "RenderEngine/RenderEngine.h" + +#include "BufferLayer.h" +#include "Layer.h" + +#include +#include +#include + +namespace android { + +class BufferStateLayer : public BufferLayer { +public: + BufferStateLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, + uint32_t w, uint32_t h, uint32_t flags); + + // ----------------------------------------------------------------------- + // Interface implementation for Layer + // ----------------------------------------------------------------------- + void onLayerDisplayed(const sp& releaseFence) override; + void setTransformHint(uint32_t orientation) const override; + void releasePendingBuffer(nsecs_t dequeueReadyTime) override; + + bool shouldPresentNow(const DispSync& dispSync) const override; + + bool getTransformToDisplayInverse() const override; + + uint32_t doTransactionResize(uint32_t flags, Layer::State* /*stateToCommit*/) override { + return flags; + } + void pushPendingState() override; + bool applyPendingStates(Layer::State* stateToCommit) override; + + uint32_t getActiveWidth(const Layer::State& s) const override { return s.active.w; } + uint32_t getActiveHeight(const Layer::State& s) const override { return s.active.h; } + Transform getActiveTransform(const Layer::State& s) const override { + return s.active.transform; + } + Region getActiveTransparentRegion(const Layer::State& s) const override { + return s.transparentRegionHint; + } + Rect getCrop(const Layer::State& s) const; + Rect getFinalCrop(const Layer::State& /*s*/) const { return Rect::EMPTY_RECT; } + + bool setTransform(uint32_t transform) override; + bool setTransformToDisplayInverse(bool transformToDisplayInverse) override; + bool setCrop(const Rect& crop) override; + bool setBuffer(sp buffer) override; + bool setAcquireFence(const sp& fence) override; + bool setDataspace(ui::Dataspace dataspace) override; + bool setHdrMetadata(const HdrMetadata& hdrMetadata) override; + bool setSurfaceDamageRegion(const Region& surfaceDamage) override; + bool setApi(int32_t api) override; + bool setSidebandStream(const sp& sidebandStream) override; + + bool setSize(uint32_t w, uint32_t h) override; + bool setPosition(float x, float y, bool immediate) override; + bool setTransparentRegionHint(const Region& transparent) override; + bool setMatrix(const layer_state_t::matrix22_t& matrix, + bool allowNonRectPreservingTransforms) override; + + // Override to ignore legacy layer state properties that are not used by BufferStateLayer + bool setCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; }; + bool setFinalCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; }; + void deferTransactionUntil_legacy(const sp& /*barrierHandle*/, + uint64_t /*frameNumber*/) override {} + void deferTransactionUntil_legacy(const sp& /*barrierLayer*/, + uint64_t /*frameNumber*/) override {} + // ----------------------------------------------------------------------- + + // ----------------------------------------------------------------------- + // Interface implementation for BufferLayer + // ----------------------------------------------------------------------- + bool fenceHasSignaled() const override; + +private: + nsecs_t getDesiredPresentTime() override; + std::shared_ptr getCurrentFenceTime() const override; + + void getDrawingTransformMatrix(float *matrix) override; + uint32_t getDrawingTransform() const override; + ui::Dataspace getDrawingDataSpace() const override; + Rect getDrawingCrop() const override; + uint32_t getDrawingScalingMode() const override; + Region getDrawingSurfaceDamage() const override; + const HdrMetadata& getDrawingHdrMetadata() const override; + int getDrawingApi() const override; + PixelFormat getPixelFormat() const override; + + uint64_t getFrameNumber() const override; + + bool getAutoRefresh() const override; + bool getSidebandStreamChanged() const override; + + std::optional latchSidebandStream(bool& recomputeVisibleRegions) override; + + bool hasDrawingBuffer() const override; + + void setFilteringEnabled(bool enabled) override; + + status_t bindTextureImage() const override; + status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override; + + status_t updateActiveBuffer() override; + status_t updateFrameNumber(nsecs_t latchTime) override; + + void setHwcLayerBuffer(const sp& display) override; + // ----------------------------------------------------------------------- +private: + void onFirstRef() override; + + std::unique_ptr mTextureImage; + + std::array mTransformMatrix; + + std::atomic mSidebandStreamChanged; + + uint32_t mFrameNumber; + + // TODO(marissaw): support sticky transform for LEGACY camera mode +}; + +} // namespace android diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 10075ae35f..bac46a38b4 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -43,7 +43,7 @@ ColorLayer::ColorLayer(SurfaceFlinger* flinger, const sp& client, const } void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */, - bool useIdentityTransform) const { + bool useIdentityTransform) { half4 color = getColor(); if (color.a > 0) { computeGeometry(renderArea, getBE().mMesh, useIdentityTransform); @@ -54,7 +54,7 @@ void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */, } } -void ColorLayer::drawNow(const RenderArea& renderArea, bool useIdentityTransform) const { +void ColorLayer::drawNow(const RenderArea& renderArea, bool useIdentityTransform) { CompositionInfo& compositionInfo = getBE().compositionInfo; auto& engine(mFlinger->getRenderEngine()); diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index 8417135ed2..429ad79a05 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -31,8 +31,8 @@ public: virtual const char* getTypeId() const { return "ColorLayer"; } virtual void onDraw(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform) const; - void drawNow(const RenderArea& , bool ) const; + bool useIdentityTransform); + void drawNow(const RenderArea&, bool); bool isVisible() const override; void setPerFrameData(const sp& display) override; diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index 320c0df86a..5ad5d562a8 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -28,9 +28,9 @@ ContainerLayer::ContainerLayer(SurfaceFlinger* flinger, const sp& client mDrawingState = mCurrentState; } -void ContainerLayer::onDraw(const RenderArea&, const Region& /* clip */, bool) const {} +void ContainerLayer::onDraw(const RenderArea&, const Region& /* clip */, bool) {} -void ContainerLayer::drawNow(const RenderArea&, bool) const {} +void ContainerLayer::drawNow(const RenderArea&, bool) {} bool ContainerLayer::isVisible() const { return !isHiddenByPolicy(); diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index 29a5c3a569..051e76523c 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -31,8 +31,8 @@ public: const char* getTypeId() const override { return "ContainerLayer"; } void onDraw(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform) const override; - void drawNow(const RenderArea& renderArea, bool useIdentityTransform) const override; + bool useIdentityTransform) override; + void drawNow(const RenderArea& renderArea, bool useIdentityTransform) override; bool isVisible() const override; void setPerFrameData(const sp& display) override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index eeee0ae863..ee9ee78fae 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -114,6 +114,17 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n mCurrentState.requested_legacy = mCurrentState.active_legacy; mCurrentState.appId = 0; mCurrentState.type = 0; + mCurrentState.active.w = 0; + mCurrentState.active.h = 0; + mCurrentState.active.transform.set(0, 0); + mCurrentState.transform = 0; + mCurrentState.transformToDisplayInverse = false; + mCurrentState.crop.makeInvalid(); + mCurrentState.acquireFence = new Fence(-1); + mCurrentState.dataspace = ui::Dataspace::UNKNOWN; + mCurrentState.hdrMetadata.validTypes = 0; + mCurrentState.surfaceDamageRegion.clear(); + mCurrentState.api = -1; // drawing state & current state are identical mDrawingState = mCurrentState; @@ -293,17 +304,19 @@ static FloatRect reduce(const FloatRect& win, const Region& exclude) { Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { const Layer::State& s(getDrawingState()); - Rect win(s.active_legacy.w, s.active_legacy.h); + Rect win(getActiveWidth(s), getActiveHeight(s)); - if (!s.crop_legacy.isEmpty()) { - win.intersect(s.crop_legacy, &win); + Rect crop = getCrop(s); + if (!crop.isEmpty()) { + win.intersect(crop, &win); } Transform t = getTransform(); win = t.transform(win); - if (!s.finalCrop_legacy.isEmpty()) { - win.intersect(s.finalCrop_legacy, &win); + Rect finalCrop = getFinalCrop(s); + if (!finalCrop.isEmpty()) { + win.intersect(finalCrop, &win); } const sp& p = mDrawingParent.promote(); @@ -322,7 +335,7 @@ Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { } if (reduceTransparentRegion) { - auto const screenTransparentRegion = t.transform(s.activeTransparentRegion_legacy); + auto const screenTransparentRegion = t.transform(getActiveTransparentRegion(s)); win = reduce(win, screenTransparentRegion); } @@ -331,15 +344,16 @@ Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { FloatRect Layer::computeBounds() const { const Layer::State& s(getDrawingState()); - return computeBounds(s.activeTransparentRegion_legacy); + return computeBounds(getActiveTransparentRegion(s)); } FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const { const Layer::State& s(getDrawingState()); - Rect win(s.active_legacy.w, s.active_legacy.h); + Rect win(getActiveWidth(s), getActiveHeight(s)); - if (!s.crop_legacy.isEmpty()) { - win.intersect(s.crop_legacy, &win); + Rect crop = getCrop(s); + if (!crop.isEmpty()) { + win.intersect(crop, &win); } const auto& p = mDrawingParent.promote(); @@ -379,9 +393,10 @@ Rect Layer::computeInitialCrop(const sp& display) const { // FIXME: the 3 lines below can produce slightly incorrect clipping when we have // a viewport clipping and a window transform. we should use floating point to fix this. - Rect activeCrop(s.active_legacy.w, s.active_legacy.h); - if (!s.crop_legacy.isEmpty()) { - activeCrop.intersect(s.crop_legacy, &activeCrop); + Rect activeCrop(getActiveWidth(s), getActiveHeight(s)); + Rect crop = getCrop(s); + if (!crop.isEmpty()) { + activeCrop.intersect(crop, &activeCrop); } Transform t = getTransform(); @@ -389,8 +404,9 @@ Rect Layer::computeInitialCrop(const sp& display) const { if (!activeCrop.intersect(display->getViewport(), &activeCrop)) { activeCrop.clear(); } - if (!s.finalCrop_legacy.isEmpty()) { - if (!activeCrop.intersect(s.finalCrop_legacy, &activeCrop)) { + Rect finalCrop = getFinalCrop(s); + if (!finalCrop.isEmpty()) { + if (!activeCrop.intersect(finalCrop, &activeCrop)) { activeCrop.clear(); } } @@ -424,12 +440,12 @@ FloatRect Layer::computeCrop(const sp& display) const { // 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_legacy.w, s.active_legacy.h), &activeCrop)) { + if (!activeCrop.intersect(Rect(getActiveWidth(s), getActiveHeight(s)), &activeCrop)) { activeCrop.clear(); } // subtract the transparent region and snap to the bounds - activeCrop = reduce(activeCrop, s.activeTransparentRegion_legacy); + activeCrop = reduce(activeCrop, getActiveTransparentRegion(s)); // Transform the window crop to match the buffer coordinate system, // which means using the inverse of the current transform set on the @@ -449,8 +465,8 @@ FloatRect Layer::computeCrop(const sp& display) const { invTransform = (Transform(invTransformOrient) * Transform(invTransform)).getOrientation(); } - int winWidth = s.active_legacy.w; - int winHeight = s.active_legacy.h; + int winWidth = getActiveWidth(s); + int winHeight = getActiveHeight(s); if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { // If the activeCrop has been rotate the ends are rotated but not // the space itself so when transforming ends back we can't rely on @@ -462,10 +478,10 @@ FloatRect Layer::computeCrop(const sp& display) const { if (is_h_flipped == is_v_flipped) { invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H; } - winWidth = s.active_legacy.h; - winHeight = s.active_legacy.w; + winWidth = getActiveHeight(s); + winHeight = getActiveWidth(s); } - const Rect winCrop = activeCrop.transform(invTransform, s.active_legacy.w, s.active_legacy.h); + const Rect winCrop = activeCrop.transform(invTransform, getActiveWidth(s), getActiveHeight(s)); // below, crop is intersected with winCrop expressed in crop's coordinate space float xScale = crop.getWidth() / float(winWidth); @@ -518,10 +534,10 @@ void Layer::setGeometry(const sp& display, uint32_t z) { // apply the layer's transform, followed by the display's global transform // here we're guaranteed that the layer's transform preserves rects - Region activeTransparentRegion(s.activeTransparentRegion_legacy); + Region activeTransparentRegion(getActiveTransparentRegion(s)); Transform t = getTransform(); - if (!s.crop_legacy.isEmpty()) { - Rect activeCrop(s.crop_legacy); + Rect activeCrop = getCrop(s); + if (!activeCrop.isEmpty()) { activeCrop = t.transform(activeCrop); if (!activeCrop.intersect(display->getViewport(), &activeCrop)) { activeCrop.clear(); @@ -533,23 +549,24 @@ void Layer::setGeometry(const sp& display, uint32_t z) { // 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_legacy.w, s.active_legacy.h), &activeCrop)) { + if (!activeCrop.intersect(Rect(getActiveWidth(s), getActiveHeight(s)), &activeCrop)) { activeCrop.clear(); } // mark regions outside the crop as transparent - activeTransparentRegion.orSelf(Rect(0, 0, s.active_legacy.w, activeCrop.top)); + activeTransparentRegion.orSelf(Rect(0, 0, getActiveWidth(s), activeCrop.top)); activeTransparentRegion.orSelf( - Rect(0, activeCrop.bottom, s.active_legacy.w, s.active_legacy.h)); + Rect(0, activeCrop.bottom, getActiveWidth(s), getActiveHeight(s))); activeTransparentRegion.orSelf(Rect(0, activeCrop.top, activeCrop.left, activeCrop.bottom)); activeTransparentRegion.orSelf( - Rect(activeCrop.right, activeCrop.top, s.active_legacy.w, activeCrop.bottom)); + Rect(activeCrop.right, activeCrop.top, getActiveWidth(s), 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_legacy.isEmpty()) { - if (!frame.intersect(s.finalCrop_legacy, &frame)) { + Rect finalCrop = getFinalCrop(s); + if (!finalCrop.isEmpty()) { + if (!frame.intersect(finalCrop, &frame)) { frame.clear(); } } @@ -682,16 +699,18 @@ void Layer::updateCursorPosition(const sp& display) { // 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_legacy.w, s.active_legacy.h); - if (!s.crop_legacy.isEmpty()) { - win.intersect(s.crop_legacy, &win); + Rect win(getActiveWidth(s), getActiveHeight(s)); + Rect crop = getCrop(s); + if (!crop.isEmpty()) { + win.intersect(crop, &win); } // Subtract the transparent region and snap to the bounds - Rect bounds = reduce(win, s.activeTransparentRegion_legacy); + Rect bounds = reduce(win, getActiveTransparentRegion(s)); Rect frame(getTransform().transform(bounds)); frame.intersect(display->getViewport(), &frame); - if (!s.finalCrop_legacy.isEmpty()) { - frame.intersect(s.finalCrop_legacy, &frame); + Rect finalCrop = getFinalCrop(s); + if (!finalCrop.isEmpty()) { + frame.intersect(finalCrop, &frame); } auto& displayTransform = display->getTransform(); auto position = displayTransform.transform(frame); @@ -709,15 +728,15 @@ void Layer::updateCursorPosition(const sp& display) { // drawing... // --------------------------------------------------------------------------- -void Layer::draw(const RenderArea& renderArea, const Region& clip) const { +void Layer::draw(const RenderArea& renderArea, const Region& clip) { onDraw(renderArea, clip, false); } -void Layer::draw(const RenderArea& renderArea, bool useIdentityTransform) const { +void Layer::draw(const RenderArea& renderArea, bool useIdentityTransform) { onDraw(renderArea, Region(renderArea.getBounds()), useIdentityTransform); } -void Layer::draw(const RenderArea& renderArea) const { +void Layer::draw(const RenderArea& renderArea) { onDraw(renderArea, Region(renderArea.getBounds()), false); } @@ -844,11 +863,12 @@ void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh, rt = layerTransform.transform(rt); } - if (!s.finalCrop_legacy.isEmpty()) { - boundPoint(<, s.finalCrop_legacy); - boundPoint(&lb, s.finalCrop_legacy); - boundPoint(&rb, s.finalCrop_legacy); - boundPoint(&rt, s.finalCrop_legacy); + Rect finalCrop = getFinalCrop(s); + if (!finalCrop.isEmpty()) { + boundPoint(<, finalCrop); + boundPoint(&lb, finalCrop); + boundPoint(&rb, finalCrop); + boundPoint(&rt, finalCrop); } Mesh::VertexArray position(mesh.getPositionArray()); @@ -984,19 +1004,11 @@ bool Layer::applyPendingStates(State* stateToCommit) { return stateUpdateAvailable; } -uint32_t Layer::doTransaction(uint32_t flags) { - ATRACE_CALL(); - - pushPendingState(); - Layer::State c = getCurrentState(); - if (!applyPendingStates(&c)) { - return 0; - } - +uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { const Layer::State& s(getDrawingState()); - const bool sizeChanged = (c.requested_legacy.w != s.requested_legacy.w) || - (c.requested_legacy.h != s.requested_legacy.h); + const bool sizeChanged = (stateToCommit->requested_legacy.w != s.requested_legacy.w) || + (stateToCommit->requested_legacy.h != s.requested_legacy.h); if (sizeChanged) { // the size changed, we need to ask our client to request a new buffer @@ -1007,16 +1019,18 @@ uint32_t Layer::doTransaction(uint32_t flags) { " 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_legacy.w, c.active_legacy.h, c.crop_legacy.left, c.crop_legacy.top, - c.crop_legacy.right, c.crop_legacy.bottom, c.crop_legacy.getWidth(), - c.crop_legacy.getHeight(), c.requested_legacy.w, c.requested_legacy.h, + stateToCommit->active_legacy.w, stateToCommit->active_legacy.h, + stateToCommit->crop_legacy.left, stateToCommit->crop_legacy.top, + stateToCommit->crop_legacy.right, stateToCommit->crop_legacy.bottom, + stateToCommit->crop_legacy.getWidth(), stateToCommit->crop_legacy.getHeight(), + stateToCommit->requested_legacy.w, stateToCommit->requested_legacy.h, s.active_legacy.w, s.active_legacy.h, s.crop_legacy.left, s.crop_legacy.top, s.crop_legacy.right, s.crop_legacy.bottom, s.crop_legacy.getWidth(), s.crop_legacy.getHeight(), s.requested_legacy.w, s.requested_legacy.h); // record the new size, form this point on, when the client request // a buffer, it'll get the new size. - setDefaultBufferSize(c.requested_legacy.w, c.requested_legacy.h); + setDefaultBufferSize(stateToCommit->requested_legacy.w, stateToCommit->requested_legacy.h); } // Don't let Layer::doTransaction update the drawing state @@ -1037,8 +1051,9 @@ uint32_t Layer::doTransaction(uint32_t flags) { // 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_legacy.w != c.active_legacy.w) || - (c.requested_legacy.h != c.active_legacy.h)) && + const bool resizePending = + ((stateToCommit->requested_legacy.w != stateToCommit->active_legacy.w) || + (stateToCommit->requested_legacy.h != stateToCommit->active_legacy.h)) && (getBE().compositionInfo.mBuffer != nullptr); if (!isFixedSize()) { if (resizePending && getBE().compositionInfo.hwc.sidebandStream == nullptr) { @@ -1062,21 +1077,37 @@ uint32_t Layer::doTransaction(uint32_t flags) { // being stored in the same data structure while having different latching rules. // b/38182305 // - // Careful that "c" and editCurrentState may not begin as equivalent due to + // Careful that "stateToCommit" and editCurrentState may not begin as equivalent due to // applyPendingStates in the presence of deferred transactions. if (mFreezeGeometryUpdates) { - float tx = c.active_legacy.transform.tx(); - float ty = c.active_legacy.transform.ty(); - c.active_legacy = c.requested_legacy; - c.active_legacy.transform.set(tx, ty); - editCurrentState.active_legacy = c.active_legacy; + float tx = stateToCommit->active_legacy.transform.tx(); + float ty = stateToCommit->active_legacy.transform.ty(); + stateToCommit->active_legacy = stateToCommit->requested_legacy; + stateToCommit->active_legacy.transform.set(tx, ty); + editCurrentState.active_legacy = stateToCommit->active_legacy; } else { editCurrentState.active_legacy = editCurrentState.requested_legacy; - c.active_legacy = c.requested_legacy; + stateToCommit->active_legacy = stateToCommit->requested_legacy; } } - if (s.active_legacy != c.active_legacy) { + return flags; +} + +uint32_t Layer::doTransaction(uint32_t flags) { + ATRACE_CALL(); + + pushPendingState(); + Layer::State c = getCurrentState(); + if (!applyPendingStates(&c)) { + return 0; + } + + flags = doTransactionResize(flags, &c); + + const Layer::State& s(getDrawingState()); + + if (getActiveGeometry(c) != getActiveGeometry(s)) { // invalidate and recompute the visible regions if needed flags |= Layer::eVisibleRegion; } @@ -1087,9 +1118,8 @@ uint32_t Layer::doTransaction(uint32_t flags) { this->contentDirty = true; // we may use linear filtering, if the matrix scales us - const uint8_t type = c.active_legacy.transform.getType(); - mNeedsFiltering = - (!c.active_legacy.transform.preserveRects() || (type >= Transform::SCALE)); + const uint8_t type = getActiveTransform(c).getType(); + mNeedsFiltering = (!getActiveTransform(c).preserveRects() || (type >= Transform::SCALE)); } // If the layer is hidden, signal and clear out all local sync points so @@ -1278,6 +1308,7 @@ bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix, setTransactionFlags(eTransactionNeeded); return true; } + bool Layer::setTransparentRegionHint(const Region& transparent) { mCurrentState.requestedTransparentRegion_legacy = transparent; mCurrentState.modified = true; @@ -1415,6 +1446,7 @@ void Layer::updateTransformHint(const sp& display) const { // debugging // ---------------------------------------------------------------------------- +// TODO(marissaw): add new layer state info to layer debugging LayerDebugInfo Layer::getLayerDebugInfo() const { LayerDebugInfo info; const Layer::State& ds = getDrawingState(); @@ -1889,14 +1921,14 @@ Transform Layer::getTransform() const { bufferHeight = p->getBE().compositionInfo.mBuffer->getWidth(); bufferWidth = p->getBE().compositionInfo.mBuffer->getHeight(); } - float sx = p->getDrawingState().active_legacy.w / static_cast(bufferWidth); - float sy = p->getDrawingState().active_legacy.h / static_cast(bufferHeight); + float sx = p->getActiveWidth(p->getDrawingState()) / static_cast(bufferWidth); + float sy = p->getActiveHeight(p->getDrawingState()) / static_cast(bufferHeight); Transform extraParentScaling; extraParentScaling.set(sx, 0, 0, sy); t = t * extraParentScaling; } } - return t * getDrawingState().active_legacy.transform; + return t * getActiveTransform(getDrawingState()); } half Layer::getAlpha() const { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 96ec84b269..a48cdffd8b 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -156,6 +156,24 @@ public: SortedVector> zOrderRelatives; half4 color; + + // The fields below this point are only used by BufferStateLayer + Geometry active; + + uint32_t transform; + bool transformToDisplayInverse; + + Rect crop; + Region transparentRegionHint; + + sp buffer; + sp acquireFence; + ui::Dataspace dataspace; + HdrMetadata hdrMetadata; + Region surfaceDamageRegion; + int32_t api; + + sp sidebandStream; }; Layer(SurfaceFlinger* flinger, const sp& client, const String8& name, uint32_t w, @@ -191,11 +209,12 @@ public: // also the rendered size of the layer prior to any transformations. Parent // or local matrix transformations will not affect the size of the buffer, // but may affect it's on-screen size or clipping. - bool setSize(uint32_t w, uint32_t h); + virtual bool setSize(uint32_t w, uint32_t h); // Set a 2x2 transformation matrix on the layer. This transform // will be applied after parent transforms, but before any final // producer specified transform. - bool setMatrix(const layer_state_t::matrix22_t& matrix, bool allowNonRectPreservingTransforms); + virtual bool setMatrix(const layer_state_t::matrix22_t& matrix, + bool allowNonRectPreservingTransforms); // This second set of geometry attributes are controlled by // setGeometryAppliesWithResize, and their default mode is to be @@ -205,32 +224,45 @@ public: // setPosition operates in parent buffer space (pre parent-transform) or display // space for top-level layers. - bool setPosition(float x, float y, bool immediate); + virtual bool setPosition(float x, float y, bool immediate); // Buffer space - bool setCrop_legacy(const Rect& crop, bool immediate); + virtual bool setCrop_legacy(const Rect& crop, bool immediate); // Parent buffer space/display space - bool setFinalCrop_legacy(const Rect& crop, bool immediate); + virtual bool setFinalCrop_legacy(const Rect& crop, bool immediate); // TODO(b/38182121): Could we eliminate the various latching modes by // using the layer hierarchy? // ----------------------------------------------------------------------- - bool setLayer(int32_t z); - bool setRelativeLayer(const sp& relativeToHandle, int32_t relativeZ); - - bool setAlpha(float alpha); - bool setColor(const half3& color); - bool setTransparentRegionHint(const Region& transparent); - bool setFlags(uint8_t flags, uint8_t mask); - bool setLayerStack(uint32_t layerStack); - uint32_t getLayerStack() const; - void deferTransactionUntil_legacy(const sp& barrierHandle, uint64_t frameNumber); - void deferTransactionUntil_legacy(const sp& barrierLayer, uint64_t frameNumber); - bool setOverrideScalingMode(int32_t overrideScalingMode); - void setInfo(int32_t type, int32_t appId); - bool reparentChildren(const sp& layer); - void setChildrenDrawingParent(const sp& layer); - bool reparent(const sp& newParentHandle); - bool detachChildren(); + virtual bool setLayer(int32_t z); + virtual bool setRelativeLayer(const sp& relativeToHandle, int32_t relativeZ); + + virtual bool setAlpha(float alpha); + virtual bool setColor(const half3& color); + virtual bool setTransparentRegionHint(const Region& transparent); + virtual bool setFlags(uint8_t flags, uint8_t mask); + virtual bool setLayerStack(uint32_t layerStack); + virtual uint32_t getLayerStack() const; + virtual void deferTransactionUntil_legacy(const sp& barrierHandle, + uint64_t frameNumber); + virtual void deferTransactionUntil_legacy(const sp& barrierLayer, uint64_t frameNumber); + virtual bool setOverrideScalingMode(int32_t overrideScalingMode); + virtual void setInfo(int32_t type, int32_t appId); + virtual bool reparentChildren(const sp& layer); + virtual void setChildrenDrawingParent(const sp& layer); + virtual bool reparent(const sp& newParentHandle); + virtual bool detachChildren(); + + // Used only to set BufferStateLayer state + virtual bool setTransform(uint32_t /*transform*/) { return false; }; + virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; }; + virtual bool setCrop(const Rect& /*crop*/) { return false; }; + virtual bool setBuffer(sp /*buffer*/) { return false; }; + virtual bool setAcquireFence(const sp& /*fence*/) { return false; }; + virtual bool setDataspace(ui::Dataspace /*dataspace*/) { return false; }; + virtual bool setHdrMetadata(const HdrMetadata& /*hdrMetadata*/) { return false; }; + virtual bool setSurfaceDamageRegion(const Region& /*surfaceDamage*/) { return false; }; + virtual bool setApi(int32_t /*api*/) { return false; }; + virtual bool setSidebandStream(const sp& /*sidebandStream*/) { return false; }; ui::Dataspace getDataSpace() const { return mCurrentDataSpace; } @@ -310,12 +342,24 @@ public: void writeToProto(LayerProto* layerInfo, int32_t displayId); + virtual Geometry getActiveGeometry(const Layer::State& s) const { return s.active_legacy; } + virtual uint32_t getActiveWidth(const Layer::State& s) const { return s.active_legacy.w; } + virtual uint32_t getActiveHeight(const Layer::State& s) const { return s.active_legacy.h; } + virtual Transform getActiveTransform(const Layer::State& s) const { + return s.active_legacy.transform; + } + virtual Region getActiveTransparentRegion(const Layer::State& s) const { + return s.activeTransparentRegion_legacy; + } + virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; } + virtual Rect getFinalCrop(const Layer::State& s) const { return s.finalCrop_legacy; } + protected: /* * onDraw - draws the surface. */ virtual void onDraw(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform) const = 0; + bool useIdentityTransform) = 0; public: virtual void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {} @@ -369,9 +413,9 @@ public: * draw - performs some global clipping optimizations * and calls onDraw(). */ - void draw(const RenderArea& renderArea, const Region& clip) const; - void draw(const RenderArea& renderArea, bool useIdentityTransform) const; - void draw(const RenderArea& renderArea) const; + void draw(const RenderArea& renderArea, const Region& clip); + void draw(const RenderArea& renderArea, bool useIdentityTransform); + void draw(const RenderArea& renderArea); /* * drawNow uses the renderEngine to draw the layer. This is different than the @@ -381,7 +425,7 @@ public: * is used for screen captures which happens separately from the frame * compositing path. */ - virtual void drawNow(const RenderArea& renderArea, bool useIdentityTransform) const = 0; + virtual void drawNow(const RenderArea& renderArea, bool useIdentityTransform) = 0; /* * doTransaction - process the transaction. This is a good place to figure @@ -536,7 +580,7 @@ public: // SurfaceFlinger to complete a transaction. void commitChildList(); int32_t getZ() const; - void pushPendingState(); + virtual void pushPendingState(); protected: // constant @@ -620,7 +664,8 @@ protected: bool addSyncPoint(const std::shared_ptr& point); void popPendingState(State* stateToCommit); - bool applyPendingStates(State* stateToCommit); + virtual bool applyPendingStates(State* stateToCommit); + virtual uint32_t doTransactionResize(uint32_t flags, Layer::State* stateToCommit); void clearSyncPoints(); diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 8b371705f1..b5acebafb1 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -78,6 +78,7 @@ public: friend class Layer; friend class BufferLayer; friend class BufferQueueLayer; + friend class BufferStateLayer; friend class ColorLayer; friend class SurfaceFlinger; diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp index fd0ca822c6..70558d4cc8 100644 --- a/services/surfaceflinger/LayerRejecter.cpp +++ b/services/surfaceflinger/LayerRejecter.cpp @@ -101,7 +101,8 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) ALOGD_IF(DEBUG_RESIZE, "[%s] latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n" - " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) " + " drawing={ active_legacy ={ wh={%4u,%4u} crop_legacy={%4d,%4d,%4d,%4d} " + "(%4d,%4d) " "}\n" " requested_legacy={ wh={%4u,%4u} }}\n", mName, bufWidth, bufHeight, item.mTransform, item.mScalingMode, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 64f1eaf463..399fbd83bc 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -64,6 +64,7 @@ #include "BufferLayer.h" #include "BufferQueueLayer.h" +#include "BufferStateLayer.h" #include "Client.h" #include "ColorLayer.h" #include "Colorizer.h" @@ -2766,7 +2767,7 @@ void SurfaceFlinger::computeVisibleRegions(const sp& displa if (translucent) { if (tr.preserveRects()) { // transform the transparent region - transparentRegion = tr.transform(s.activeTransparentRegion_legacy); + transparentRegion = tr.transform(layer->getActiveTransparentRegion(s)); } else { // transformation too complex, can't do the // transparent region optimization. @@ -3551,6 +3552,37 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState // We don't trigger a traversal here because if no other state is // changed, we don't want this to cause any more work } + if (what & layer_state_t::eTransformChanged) { + if (layer->setTransform(s.transform)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eTransformToDisplayInverseChanged) { + if (layer->setTransformToDisplayInverse(s.transformToDisplayInverse)) + flags |= eTraversalNeeded; + } + if (what & layer_state_t::eCropChanged) { + if (layer->setCrop(s.crop)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eBufferChanged) { + if (layer->setBuffer(s.buffer)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eAcquireFenceChanged) { + if (layer->setAcquireFence(s.acquireFence)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eDataspaceChanged) { + if (layer->setDataspace(s.dataspace)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eHdrMetadataChanged) { + if (layer->setHdrMetadata(s.hdrMetadata)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eSurfaceDamageRegionChanged) { + if (layer->setSurfaceDamageRegion(s.surfaceDamageRegion)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eApiChanged) { + if (layer->setApi(s.api)) flags |= eTraversalNeeded; + } + if (what & layer_state_t::eSidebandStreamChanged) { + if (layer->setSidebandStream(s.sidebandStream)) flags |= eTraversalNeeded; + } return flags; } @@ -3593,10 +3625,13 @@ status_t SurfaceFlinger::createLayer( String8 uniqueName = getUniqueLayerName(name); switch (flags & ISurfaceComposerClient::eFXSurfaceMask) { - case ISurfaceComposerClient::eFXSurfaceNormal: + case ISurfaceComposerClient::eFXSurfaceBufferQueue: result = createBufferQueueLayer(client, uniqueName, w, h, flags, format, handle, gbp, &layer); + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + result = createBufferStateLayer(client, uniqueName, w, h, flags, handle, &layer); break; case ISurfaceComposerClient::eFXSurfaceColor: result = createColorLayer(client, @@ -3687,6 +3722,16 @@ status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, const return err; } +status_t SurfaceFlinger::createBufferStateLayer(const sp& client, const String8& name, + uint32_t w, uint32_t h, uint32_t flags, + sp* handle, sp* outLayer) { + sp layer = new BufferStateLayer(this, client, name, w, h, flags); + *handle = layer->getHandle(); + *outLayer = layer; + + return NO_ERROR; +} + status_t SurfaceFlinger::createColorLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, sp* handle, sp* outLayer) @@ -4864,10 +4909,12 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, const Transform& getTransform() const override { return mTransform; } Rect getBounds() const override { const Layer::State& layerState(mLayer->getDrawingState()); - return Rect(layerState.active_legacy.w, layerState.active_legacy.h); + return Rect(mLayer->getActiveWidth(layerState), mLayer->getActiveHeight(layerState)); + } + int getHeight() const override { + return mLayer->getActiveHeight(mLayer->getDrawingState()); } - int getHeight() const override { return mLayer->getDrawingState().active_legacy.h; } - int getWidth() const override { return mLayer->getDrawingState().active_legacy.w; } + int getWidth() const override { return mLayer->getActiveWidth(mLayer->getDrawingState()); } bool isSecure() const override { return false; } bool needsFiltering() const override { return false; } Rect getSourceCrop() const override { @@ -4935,12 +4982,12 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, Rect crop(sourceCrop); if (sourceCrop.width() <= 0) { crop.left = 0; - crop.right = parent->getCurrentState().active_legacy.w; + crop.right = parent->getActiveWidth(parent->getCurrentState()); } if (sourceCrop.height() <= 0) { crop.top = 0; - crop.bottom = parent->getCurrentState().active_legacy.h; + crop.bottom = parent->getActiveHeight(parent->getCurrentState()); } int32_t reqWidth = crop.width() * frameScale; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index a750636520..eaaf7420f1 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -356,6 +356,7 @@ private: friend class Layer; friend class BufferLayer; friend class BufferQueueLayer; + friend class BufferStateLayer; friend class MonitoredProducer; // For unit tests @@ -535,6 +536,10 @@ private: sp* outHandle, sp* outGbp, sp* outLayer); + status_t createBufferStateLayer(const sp& client, const String8& name, uint32_t w, + uint32_t h, uint32_t flags, sp* outHandle, + sp* outLayer); + status_t createColorLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, sp* outHandle, sp* outLayer); diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index c42213a28d..f504c13a97 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -30,6 +30,7 @@ namespace android { // ---------------------------------------------------------------------------- +// TODO(marissaw): add new layer state values to SurfaceInterceptor SurfaceInterceptor::~SurfaceInterceptor() = default; diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 2ce32b5967..bde6614b61 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -62,38 +62,54 @@ const Color Color::WHITE{255, 255, 255, 255}; const Color Color::BLACK{0, 0, 0, 255}; const Color Color::TRANSPARENT{0, 0, 0, 0}; +using android::hardware::graphics::common::V1_1::BufferUsage; + std::ostream& operator<<(std::ostream& os, const Color& color) { os << int(color.r) << ", " << int(color.g) << ", " << int(color.b) << ", " << int(color.a); return os; } // Fill a region with the specified color. -void fillBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect, const Color& color) { - int32_t x = rect.left; - int32_t y = rect.top; - int32_t width = rect.right - rect.left; - int32_t height = rect.bottom - rect.top; - - if (x < 0) { - width += x; - x = 0; +void fillANativeWindowBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect, + const Color& color) { + Rect r(0, 0, buffer.width, buffer.height); + if (!r.intersect(rect, &r)) { + return; } - if (y < 0) { - height += y; - y = 0; - } - if (x + width > buffer.width) { - x = std::min(x, buffer.width); - width = buffer.width - x; + + int32_t width = r.right - r.left; + int32_t height = r.bottom - r.top; + + for (int32_t row = 0; row < height; row++) { + uint8_t* dst = + static_cast(buffer.bits) + (buffer.stride * (r.top + row) + r.left) * 4; + for (int32_t column = 0; column < width; column++) { + dst[0] = color.r; + dst[1] = color.g; + dst[2] = color.b; + dst[3] = color.a; + dst += 4; + } } - if (y + height > buffer.height) { - y = std::min(y, buffer.height); - height = buffer.height - y; +} + +// Fill a region with the specified color. +void fillGraphicBufferColor(const sp& buffer, const Rect& rect, const Color& color) { + Rect r(0, 0, buffer->width, buffer->height); + if (!r.intersect(rect, &r)) { + return; } - for (int32_t j = 0; j < height; j++) { - uint8_t* dst = static_cast(buffer.bits) + (buffer.stride * (y + j) + x) * 4; - for (int32_t i = 0; i < width; i++) { + int32_t width = r.right - r.left; + int32_t height = r.bottom - r.top; + + uint8_t* pixels; + buffer->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); + + for (int32_t row = 0; row < height; row++) { + uint8_t* dst = pixels + (buffer->getStride() * (r.top + row) + r.left) * 4; + for (int32_t column = 0; column < width; column++) { dst[0] = color.r; dst[1] = color.g; dst[2] = color.b; @@ -101,6 +117,7 @@ void fillBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect, const dst += 4; } } + buffer->unlock(); } // Check if a region has the specified color. @@ -301,8 +318,8 @@ protected: ASSERT_NO_FATAL_FAILURE(SetUpDisplay()); } - sp createLayer(const char* name, uint32_t width, uint32_t height, - uint32_t flags = 0) { + virtual sp createLayer(const char* name, uint32_t width, uint32_t height, + uint32_t flags = 0) { auto layer = mClient->createSurface(String8(name), width, height, PIXEL_FORMAT_RGBA_8888, flags); EXPECT_NE(nullptr, layer.get()) << "failed to create SurfaceControl"; @@ -319,7 +336,7 @@ protected: return layer; } - ANativeWindow_Buffer getLayerBuffer(const sp& layer) { + ANativeWindow_Buffer getBufferQueueLayerBuffer(const sp& layer) { // wait for previous transactions (such as setSize) to complete Transaction().apply(true); @@ -329,35 +346,103 @@ protected: return buffer; } - void postLayerBuffer(const sp& layer) { + void postBufferQueueLayerBuffer(const sp& layer) { ASSERT_EQ(NO_ERROR, layer->getSurface()->unlockAndPost()); // wait for the newly posted buffer to be latched waitForLayerBuffers(); } - void fillLayerColor(const sp& layer, const Color& color) { + virtual void fillBufferQueueLayerColor(const sp& layer, const Color& color, + int32_t bufferWidth, int32_t bufferHeight) { ANativeWindow_Buffer buffer; - ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer)); - fillBufferColor(buffer, Rect(0, 0, buffer.width, buffer.height), color); - postLayerBuffer(layer); + ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); + fillANativeWindowBufferColor(buffer, Rect(0, 0, bufferWidth, bufferHeight), color); + postBufferQueueLayerBuffer(layer); + } + + virtual void fillBufferStateLayerColor(const sp& layer, const Color& color, + int32_t bufferWidth, int32_t bufferHeight) { + sp buffer = + new GraphicBuffer(bufferWidth, bufferHeight, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + fillGraphicBufferColor(buffer, Rect(0, 0, bufferWidth, bufferHeight), color); + Transaction().setBuffer(layer, buffer).setSize(layer, bufferWidth, bufferHeight).apply(); + } + + void fillLayerColor(uint32_t mLayerType, const sp& layer, const Color& color, + int32_t bufferWidth, int32_t bufferHeight) { + switch (mLayerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + fillBufferQueueLayerColor(layer, color, bufferWidth, bufferHeight); + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + fillBufferStateLayerColor(layer, color, bufferWidth, bufferHeight); + break; + default: + ASSERT_TRUE(false) << "unsupported layer type: " << mLayerType; + } } - void fillLayerQuadrant(const sp& layer, const Color& topLeft, + void fillLayerQuadrant(uint32_t mLayerType, const sp& layer, + int32_t bufferWidth, int32_t bufferHeight, const Color& topLeft, const Color& topRight, const Color& bottomLeft, const Color& bottomRight) { + switch (mLayerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + fillBufferQueueLayerQuadrant(layer, bufferWidth, bufferHeight, topLeft, topRight, + bottomLeft, bottomRight); + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + fillBufferStateLayerQuadrant(layer, bufferWidth, bufferHeight, topLeft, topRight, + bottomLeft, bottomRight); + break; + default: + ASSERT_TRUE(false) << "unsupported layer type: " << mLayerType; + } + } + + virtual void fillBufferQueueLayerQuadrant(const sp& layer, int32_t bufferWidth, + int32_t bufferHeight, const Color& topLeft, + const Color& topRight, const Color& bottomLeft, + const Color& bottomRight) { ANativeWindow_Buffer buffer; - ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer)); - ASSERT_TRUE(buffer.width % 2 == 0 && buffer.height % 2 == 0); + ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); + ASSERT_TRUE(bufferWidth % 2 == 0 && bufferHeight % 2 == 0); + + const int32_t halfW = bufferWidth / 2; + const int32_t halfH = bufferHeight / 2; + fillANativeWindowBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft); + fillANativeWindowBufferColor(buffer, Rect(halfW, 0, bufferWidth, halfH), topRight); + fillANativeWindowBufferColor(buffer, Rect(0, halfH, halfW, bufferHeight), bottomLeft); + fillANativeWindowBufferColor(buffer, Rect(halfW, halfH, bufferWidth, bufferHeight), + bottomRight); + + postBufferQueueLayerBuffer(layer); + } - const int32_t halfW = buffer.width / 2; - const int32_t halfH = buffer.height / 2; - fillBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft); - fillBufferColor(buffer, Rect(halfW, 0, buffer.width, halfH), topRight); - fillBufferColor(buffer, Rect(0, halfH, halfW, buffer.height), bottomLeft); - fillBufferColor(buffer, Rect(halfW, halfH, buffer.width, buffer.height), bottomRight); + virtual void fillBufferStateLayerQuadrant(const sp& layer, int32_t bufferWidth, + int32_t bufferHeight, const Color& topLeft, + const Color& topRight, const Color& bottomLeft, + const Color& bottomRight) { + sp buffer = + new GraphicBuffer(bufferWidth, bufferHeight, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); - postLayerBuffer(layer); + ASSERT_TRUE(bufferWidth % 2 == 0 && bufferHeight % 2 == 0); + + const int32_t halfW = bufferWidth / 2; + const int32_t halfH = bufferHeight / 2; + fillGraphicBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft); + fillGraphicBufferColor(buffer, Rect(halfW, 0, bufferWidth, halfH), topRight); + fillGraphicBufferColor(buffer, Rect(0, halfH, halfW, bufferHeight), bottomLeft); + fillGraphicBufferColor(buffer, Rect(halfW, halfH, bufferWidth, bufferHeight), bottomRight); + + Transaction().setBuffer(layer, buffer).setSize(layer, bufferWidth, bufferHeight).apply(); } sp screenshot() { @@ -376,6 +461,10 @@ protected: // leave room for ~256 layers const int32_t mLayerZBase = std::numeric_limits::max() - 256; + void setPositionWithResizeHelper(uint32_t layerType); + void setSizeBasicHelper(uint32_t layerType); + void setMatrixWithResizeHelper(uint32_t layerType); + private: void SetUpDisplay() { mDisplay = mClient->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain); @@ -404,10 +493,48 @@ private: int32_t mBufferPostDelay; }; -TEST_F(LayerTransactionTest, SetPositionBasic) { +class LayerTypeTransactionTest : public LayerTransactionTest, + public ::testing::WithParamInterface { +public: + LayerTypeTransactionTest() { mLayerType = GetParam(); } + + sp createLayer(const char* name, uint32_t width, uint32_t height, + uint32_t flags = 0) override { + // if the flags already have a layer type specified, return an error + if (flags & ISurfaceComposerClient::eFXSurfaceMask) { + return nullptr; + } + return LayerTransactionTest::createLayer(name, width, height, flags | mLayerType); + } + + void fillLayerColor(const sp& layer, const Color& color, int32_t bufferWidth, + int32_t bufferHeight) { + ASSERT_NO_FATAL_FAILURE(LayerTransactionTest::fillLayerColor(mLayerType, layer, color, + bufferWidth, bufferHeight)); + } + + void fillLayerQuadrant(const sp& layer, int32_t bufferWidth, + int32_t bufferHeight, const Color& topLeft, const Color& topRight, + const Color& bottomLeft, const Color& bottomRight) { + ASSERT_NO_FATAL_FAILURE(LayerTransactionTest::fillLayerQuadrant(mLayerType, layer, + bufferWidth, bufferHeight, + topLeft, topRight, + bottomLeft, bottomRight)); + } + +protected: + uint32_t mLayerType; +}; + +INSTANTIATE_TEST_CASE_P( + LayerTypeTransactionTests, LayerTypeTransactionTest, + ::testing::Values(static_cast(ISurfaceComposerClient::eFXSurfaceBufferQueue), + static_cast(ISurfaceComposerClient::eFXSurfaceBufferState))); + +TEST_P(LayerTypeTransactionTest, SetPositionBasic) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); { SCOPED_TRACE("default position"); @@ -425,10 +552,10 @@ TEST_F(LayerTransactionTest, SetPositionBasic) { } } -TEST_F(LayerTransactionTest, SetPositionRounding) { +TEST_P(LayerTypeTransactionTest, SetPositionRounding) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); // GLES requires only 4 bits of subpixel precision during rasterization // XXX GLES composition does not match HWC composition due to precision @@ -447,10 +574,10 @@ TEST_F(LayerTransactionTest, SetPositionRounding) { } } -TEST_F(LayerTransactionTest, SetPositionOutOfBounds) { +TEST_P(LayerTypeTransactionTest, SetPositionOutOfBounds) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); Transaction().setPosition(layer, -32, -32).apply(); { @@ -465,10 +592,10 @@ TEST_F(LayerTransactionTest, SetPositionOutOfBounds) { } } -TEST_F(LayerTransactionTest, SetPositionPartiallyOutOfBounds) { +TEST_P(LayerTypeTransactionTest, SetPositionPartiallyOutOfBounds) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); // partially out of bounds Transaction().setPosition(layer, -30, -30).apply(); @@ -486,10 +613,10 @@ TEST_F(LayerTransactionTest, SetPositionPartiallyOutOfBounds) { } } -TEST_F(LayerTransactionTest, SetPositionWithResize) { +void LayerTransactionTest::setPositionWithResizeHelper(uint32_t layerType) { sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 32, 32)); // setPosition is applied immediately by default, with or without resize // pending @@ -497,21 +624,43 @@ TEST_F(LayerTransactionTest, SetPositionWithResize) { { SCOPED_TRACE("resize pending"); auto shot = screenshot(); - shot->expectColor(Rect(5, 10, 37, 42), Color::RED); - shot->expectBorder(Rect(5, 10, 37, 42), Color::BLACK); + Rect rect; + switch (layerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + rect = {5, 10, 37, 42}; + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + rect = {5, 10, 69, 74}; + break; + default: + ASSERT_FALSE(true) << "Unsupported layer type"; + } + + shot->expectColor(rect, Color::RED); + shot->expectBorder(rect, Color::BLACK); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 64, 64)); { SCOPED_TRACE("resize applied"); screenshot()->expectColor(Rect(5, 10, 69, 74), Color::RED); } } -TEST_F(LayerTransactionTest, SetPositionWithNextResize) { +TEST_F(LayerTransactionTest, SetPositionWithResize_BufferQueue) { + ASSERT_NO_FATAL_FAILURE( + setPositionWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue)); +} + +TEST_F(LayerTransactionTest, SetPositionWithResize_BufferState) { + ASSERT_NO_FATAL_FAILURE( + setPositionWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferState)); +} + +TEST_F(LayerTransactionTest, SetPositionWithNextResize_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // request setPosition to be applied with the next resize Transaction().setPosition(layer, 5, 10).setGeometryAppliesWithResize(layer).apply(); @@ -533,17 +682,17 @@ TEST_F(LayerTransactionTest, SetPositionWithNextResize) { } // finally resize and latch the buffer - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64)); { SCOPED_TRACE("new position applied"); screenshot()->expectColor(Rect(15, 20, 79, 84), Color::RED); } } -TEST_F(LayerTransactionTest, SetPositionWithNextResizeScaleToWindow) { +TEST_F(LayerTransactionTest, SetPositionWithNextResizeScaleToWindow_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // setPosition is not immediate even with SCALE_TO_WINDOW override Transaction() @@ -557,27 +706,38 @@ TEST_F(LayerTransactionTest, SetPositionWithNextResizeScaleToWindow) { screenshot()->expectColor(Rect(0, 0, 64, 64), Color::RED); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64)); { SCOPED_TRACE("new position applied"); screenshot()->expectColor(Rect(5, 10, 69, 74), Color::RED); } } -TEST_F(LayerTransactionTest, SetSizeBasic) { +void LayerTransactionTest::setSizeBasicHelper(uint32_t layerType) { sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 32, 32)); Transaction().setSize(layer, 64, 64).apply(); { SCOPED_TRACE("resize pending"); auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + Rect rect; + switch (layerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + rect = {0, 0, 32, 32}; + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + rect = {0, 0, 64, 64}; + break; + default: + ASSERT_FALSE(true) << "Unsupported layer type"; + } + shot->expectColor(rect, Color::RED); + shot->expectBorder(rect, Color::BLACK); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 64, 64)); { SCOPED_TRACE("resize applied"); auto shot = screenshot(); @@ -586,14 +746,22 @@ TEST_F(LayerTransactionTest, SetSizeBasic) { } } -TEST_F(LayerTransactionTest, SetSizeInvalid) { +TEST_F(LayerTransactionTest, SetSizeBasic_BufferQueue) { + setSizeBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue); +} + +TEST_F(LayerTransactionTest, SetSizeBasic_BufferState) { + setSizeBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferState); +} + +TEST_P(LayerTypeTransactionTest, SetSizeInvalid) { // cannot test robustness against invalid sizes (zero or really huge) } -TEST_F(LayerTransactionTest, SetSizeWithScaleToWindow) { +TEST_P(LayerTypeTransactionTest, SetSizeWithScaleToWindow) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); // setSize is immediate with SCALE_TO_WINDOW, unlike setPosition Transaction() @@ -603,13 +771,13 @@ TEST_F(LayerTransactionTest, SetSizeWithScaleToWindow) { screenshot()->expectColor(Rect(0, 0, 64, 64), Color::RED); } -TEST_F(LayerTransactionTest, SetZBasic) { +TEST_P(LayerTypeTransactionTest, SetZBasic) { sp layerR; sp layerG; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); Transaction().setLayer(layerR, mLayerZBase + 1).apply(); { @@ -624,13 +792,13 @@ TEST_F(LayerTransactionTest, SetZBasic) { } } -TEST_F(LayerTransactionTest, SetZNegative) { +TEST_P(LayerTypeTransactionTest, SetZNegative) { sp layerR; sp layerG; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); Transaction().setLayer(layerR, -1).setLayer(layerG, -2).apply(); { @@ -649,13 +817,13 @@ TEST_F(LayerTransactionTest, SetZNegative) { } } -TEST_F(LayerTransactionTest, SetRelativeZBasic) { +TEST_P(LayerTypeTransactionTest, SetRelativeZBasic) { sp layerR; sp layerG; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); Transaction() .setPosition(layerG, 16, 16) @@ -677,16 +845,16 @@ TEST_F(LayerTransactionTest, SetRelativeZBasic) { } } -TEST_F(LayerTransactionTest, SetRelativeZNegative) { +TEST_P(LayerTypeTransactionTest, SetRelativeZNegative) { sp layerR; sp layerG; sp layerB; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE, 32, 32)); // layerR = mLayerZBase, layerG = layerR - 1, layerB = -2 Transaction().setRelativeLayer(layerG, layerR->getHandle(), -1).setLayer(layerB, -2).apply(); @@ -697,16 +865,16 @@ TEST_F(LayerTransactionTest, SetRelativeZNegative) { screenshot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); } -TEST_F(LayerTransactionTest, SetRelativeZGroup) { +TEST_P(LayerTypeTransactionTest, SetRelativeZGroup) { sp layerR; sp layerG; sp layerB; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE, 32, 32)); // layerR = 0, layerG = layerR + 3, layerB = 2 Transaction() @@ -764,14 +932,14 @@ TEST_F(LayerTransactionTest, SetRelativeZGroup) { } } -TEST_F(LayerTransactionTest, SetRelativeZBug64572777) { +TEST_P(LayerTypeTransactionTest, SetRelativeZBug64572777) { sp layerR; sp layerG; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); Transaction() .setPosition(layerG, 16, 16) @@ -783,10 +951,10 @@ TEST_F(LayerTransactionTest, SetRelativeZBug64572777) { screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } -TEST_F(LayerTransactionTest, SetFlagsHidden) { +TEST_P(LayerTypeTransactionTest, SetFlagsHidden) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); Transaction().setFlags(layer, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden).apply(); { @@ -801,14 +969,14 @@ TEST_F(LayerTransactionTest, SetFlagsHidden) { } } -TEST_F(LayerTransactionTest, SetFlagsOpaque) { +TEST_P(LayerTypeTransactionTest, SetFlagsOpaque) { const Color translucentRed = {100, 0, 0, 100}; sp layerR; sp layerG; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, translucentRed)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, translucentRed, 32, 32)); ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); Transaction() .setLayer(layerR, mLayerZBase + 1) @@ -827,10 +995,10 @@ TEST_F(LayerTransactionTest, SetFlagsOpaque) { } } -TEST_F(LayerTransactionTest, SetFlagsSecure) { +TEST_P(LayerTypeTransactionTest, SetFlagsSecure) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); sp composer = ComposerService::getComposerService(); sp outBuffer; @@ -847,19 +1015,19 @@ TEST_F(LayerTransactionTest, SetFlagsSecure) { false)); } -TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic) { +TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic_BufferQueue) { const Rect top(0, 0, 32, 16); const Rect bottom(0, 16, 32, 32); sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ANativeWindow_Buffer buffer; - ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer)); - ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, top, Color::TRANSPARENT)); - ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, bottom, Color::RED)); + ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); + ASSERT_NO_FATAL_FAILURE(fillANativeWindowBufferColor(buffer, top, Color::TRANSPARENT)); + ASSERT_NO_FATAL_FAILURE(fillANativeWindowBufferColor(buffer, bottom, Color::RED)); // setTransparentRegionHint always applies to the following buffer Transaction().setTransparentRegionHint(layer, Region(top)).apply(); - ASSERT_NO_FATAL_FAILURE(postLayerBuffer(layer)); + ASSERT_NO_FATAL_FAILURE(postBufferQueueLayerBuffer(layer)); { SCOPED_TRACE("top transparent"); auto shot = screenshot(); @@ -875,10 +1043,10 @@ TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic) { shot->expectColor(bottom, Color::RED); } - ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer)); - ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, top, Color::RED)); - ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, bottom, Color::TRANSPARENT)); - ASSERT_NO_FATAL_FAILURE(postLayerBuffer(layer)); + ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); + ASSERT_NO_FATAL_FAILURE(fillANativeWindowBufferColor(buffer, top, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillANativeWindowBufferColor(buffer, bottom, Color::TRANSPARENT)); + ASSERT_NO_FATAL_FAILURE(postBufferQueueLayerBuffer(layer)); { SCOPED_TRACE("bottom transparent"); auto shot = screenshot(); @@ -887,7 +1055,58 @@ TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic) { } } -TEST_F(LayerTransactionTest, SetTransparentRegionHintOutOfBounds) { +TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic_BufferState) { + const Rect top(0, 0, 32, 16); + const Rect bottom(0, 16, 32, 32); + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + + ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, top, Color::TRANSPARENT)); + ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, bottom, Color::RED)); + Transaction() + .setTransparentRegionHint(layer, Region(top)) + .setBuffer(layer, buffer) + .setSize(layer, 32, 32) + .apply(); + { + SCOPED_TRACE("top transparent"); + auto shot = screenshot(); + shot->expectColor(top, Color::BLACK); + shot->expectColor(bottom, Color::RED); + } + + Transaction().setTransparentRegionHint(layer, Region(bottom)).apply(); + { + SCOPED_TRACE("transparent region hint intermediate"); + auto shot = screenshot(); + shot->expectColor(top, Color::BLACK); + shot->expectColor(bottom, Color::BLACK); + } + + buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + + ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, top, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, bottom, Color::TRANSPARENT)); + Transaction().setBuffer(layer, buffer).setSize(layer, 32, 32).apply(); + { + SCOPED_TRACE("bottom transparent"); + auto shot = screenshot(); + shot->expectColor(top, Color::RED); + shot->expectColor(bottom, Color::BLACK); + } +} + +TEST_P(LayerTypeTransactionTest, SetTransparentRegionHintOutOfBounds) { sp layerTransparent; sp layerR; ASSERT_NO_FATAL_FAILURE(layerTransparent = createLayer("test transparent", 32, 32)); @@ -900,18 +1119,18 @@ TEST_F(LayerTransactionTest, SetTransparentRegionHintOutOfBounds) { .setPosition(layerR, 16, 16) .setLayer(layerR, mLayerZBase + 1) .apply(); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerTransparent, Color::TRANSPARENT)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerTransparent, Color::TRANSPARENT, 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); screenshot()->expectColor(Rect(16, 16, 48, 48), Color::RED); } -TEST_F(LayerTransactionTest, SetAlphaBasic) { +TEST_P(LayerTypeTransactionTest, SetAlphaBasic) { sp layer1; sp layer2; ASSERT_NO_FATAL_FAILURE(layer1 = createLayer("test 1", 32, 32)); ASSERT_NO_FATAL_FAILURE(layer2 = createLayer("test 2", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer1, {64, 0, 0, 255})); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer2, {0, 64, 0, 255})); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer1, {64, 0, 0, 255}, 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer2, {0, 64, 0, 255}, 32, 32)); Transaction() .setAlpha(layer1, 0.25f) @@ -931,11 +1150,11 @@ TEST_F(LayerTransactionTest, SetAlphaBasic) { } } -TEST_F(LayerTransactionTest, SetAlphaClamped) { +TEST_P(LayerTypeTransactionTest, SetAlphaClamped) { const Color color = {64, 0, 0, 255}; sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, color)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, color, 32, 32)); Transaction().setAlpha(layer, 2.0f).apply(); { @@ -954,7 +1173,7 @@ TEST_F(LayerTransactionTest, SetColorBasic) { sp bufferLayer; sp colorLayer; ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE( colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor)); @@ -989,7 +1208,7 @@ TEST_F(LayerTransactionTest, SetColorWithAlpha) { sp bufferLayer; sp colorLayer; ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE( colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor)); @@ -1014,7 +1233,7 @@ TEST_F(LayerTransactionTest, SetColorWithParentAlpha_Bug74220420) { sp colorLayer; ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32)); ASSERT_NO_FATAL_FAILURE(parentLayer = createLayer("parentWithAlpha", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE(colorLayer = createLayer( "childWithColor", 32, 32, ISurfaceComposerClient::eFXSurfaceColor)); @@ -1034,20 +1253,20 @@ TEST_F(LayerTransactionTest, SetColorWithParentAlpha_Bug74220420) { tolerance); } -TEST_F(LayerTransactionTest, SetColorWithBuffer) { +TEST_P(LayerTypeTransactionTest, SetColorWithBuffer) { sp bufferLayer; ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED, 32, 32)); // color is ignored Transaction().setColor(bufferLayer, half3(0.0f, 1.0f, 0.0f)).apply(); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } -TEST_F(LayerTransactionTest, SetLayerStackBasic) { +TEST_P(LayerTypeTransactionTest, SetLayerStackBasic) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); Transaction().setLayerStack(layer, mDisplayLayerStack + 1).apply(); { @@ -1062,11 +1281,11 @@ TEST_F(LayerTransactionTest, SetLayerStackBasic) { } } -TEST_F(LayerTransactionTest, SetMatrixBasic) { +TEST_P(LayerTypeTransactionTest, SetMatrixBasic) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ASSERT_NO_FATAL_FAILURE( - fillLayerQuadrant(layer, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); + fillLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f).setPosition(layer, 0, 0).apply(); { @@ -1104,11 +1323,11 @@ TEST_F(LayerTransactionTest, SetMatrixBasic) { } } -TEST_F(LayerTransactionTest, SetMatrixRot45) { +TEST_P(LayerTypeTransactionTest, SetMatrixRot45) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ASSERT_NO_FATAL_FAILURE( - fillLayerQuadrant(layer, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); + fillLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); const float rot = M_SQRT1_2; // 45 degrees const float trans = M_SQRT2 * 16.0f; @@ -1127,31 +1346,52 @@ TEST_F(LayerTransactionTest, SetMatrixRot45) { shot->expectColor(get8x8Rect(2 * unit, 3 * unit), Color::WHITE); } -TEST_F(LayerTransactionTest, SetMatrixWithResize) { +void LayerTransactionTest::setMatrixWithResizeHelper(uint32_t layerType) { sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 32, 32)); // setMatrix is applied after any pending resize, unlike setPosition Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).setSize(layer, 64, 64).apply(); { SCOPED_TRACE("resize pending"); auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + Rect rect; + switch (layerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + rect = {0, 0, 32, 32}; + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + rect = {0, 0, 128, 128}; + break; + default: + ASSERT_FALSE(true) << "Unsupported layer type"; + } + shot->expectColor(rect, Color::RED); + shot->expectBorder(rect, Color::BLACK); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 64, 64)); { SCOPED_TRACE("resize applied"); screenshot()->expectColor(Rect(0, 0, 128, 128), Color::RED); } } -TEST_F(LayerTransactionTest, SetMatrixWithScaleToWindow) { +TEST_F(LayerTransactionTest, SetMatrixWithResize_BufferQueue) { + ASSERT_NO_FATAL_FAILURE( + setMatrixWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue)); +} + +TEST_F(LayerTransactionTest, SetMatrixWithResize_BufferState) { + ASSERT_NO_FATAL_FAILURE( + setMatrixWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferState)); +} + +TEST_P(LayerTypeTransactionTest, SetMatrixWithScaleToWindow) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); // setMatrix is immediate with SCALE_TO_WINDOW, unlike setPosition Transaction() @@ -1162,11 +1402,11 @@ TEST_F(LayerTransactionTest, SetMatrixWithScaleToWindow) { screenshot()->expectColor(Rect(0, 0, 128, 128), Color::RED); } -TEST_F(LayerTransactionTest, SetOverrideScalingModeBasic) { +TEST_P(LayerTypeTransactionTest, SetOverrideScalingModeBasic) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ASSERT_NO_FATAL_FAILURE( - fillLayerQuadrant(layer, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); + fillLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); // XXX SCALE_CROP is not respected; calling setSize and // setOverrideScalingMode in separate transactions does not work @@ -1182,10 +1422,10 @@ TEST_F(LayerTransactionTest, SetOverrideScalingModeBasic) { } } -TEST_F(LayerTransactionTest, SetCropBasic) { +TEST_F(LayerTransactionTest, SetCropBasic_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); const Rect crop(8, 8, 24, 24); Transaction().setCrop_legacy(layer, crop).apply(); @@ -1194,10 +1434,23 @@ TEST_F(LayerTransactionTest, SetCropBasic) { shot->expectBorder(crop, Color::BLACK); } -TEST_F(LayerTransactionTest, SetCropEmpty) { +TEST_F(LayerTransactionTest, SetCropBasic_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + const Rect crop(8, 8, 24, 24); + + Transaction().setCrop(layer, crop).apply(); + auto shot = screenshot(); + shot->expectColor(crop, Color::RED); + shot->expectBorder(crop, Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetCropEmpty_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); { SCOPED_TRACE("empty rect"); @@ -1212,10 +1465,29 @@ TEST_F(LayerTransactionTest, SetCropEmpty) { } } -TEST_F(LayerTransactionTest, SetCropOutOfBounds) { +TEST_F(LayerTransactionTest, SetCropEmpty_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + { + SCOPED_TRACE("empty rect"); + Transaction().setCrop(layer, Rect(8, 8, 8, 8)).apply(); + screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); + } + + { + SCOPED_TRACE("negative rect"); + Transaction().setCrop(layer, Rect(8, 8, 0, 0)).apply(); + screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); + } +} + +TEST_F(LayerTransactionTest, SetCropOutOfBounds_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); Transaction().setCrop_legacy(layer, Rect(-128, -64, 128, 64)).apply(); auto shot = screenshot(); @@ -1223,10 +1495,22 @@ TEST_F(LayerTransactionTest, SetCropOutOfBounds) { shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } -TEST_F(LayerTransactionTest, SetCropWithTranslation) { +TEST_F(LayerTransactionTest, SetCropOutOfBounds_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + Transaction().setCrop(layer, Rect(-128, -64, 128, 64)).apply(); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetCropWithTranslation_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); const Point position(32, 32); const Rect crop(8, 8, 24, 24); @@ -1236,10 +1520,24 @@ TEST_F(LayerTransactionTest, SetCropWithTranslation) { shot->expectBorder(crop + position, Color::BLACK); } -TEST_F(LayerTransactionTest, SetCropWithScale) { +TEST_F(LayerTransactionTest, SetCropWithTranslation_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + const Point position(32, 32); + const Rect crop(8, 8, 24, 24); + Transaction().setPosition(layer, position.x, position.y).setCrop(layer, crop).apply(); + auto shot = screenshot(); + shot->expectColor(crop + position, Color::RED); + shot->expectBorder(crop + position, Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetCropWithScale_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // crop is affected by matrix Transaction() @@ -1251,10 +1549,26 @@ TEST_F(LayerTransactionTest, SetCropWithScale) { shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK); } -TEST_F(LayerTransactionTest, SetCropWithResize) { +TEST_F(LayerTransactionTest, SetCropWithScale_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + // crop is affected by matrix + Transaction() + .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f) + .setCrop(layer, Rect(8, 8, 24, 24)) + .apply(); + auto shot = screenshot(); + shot->expectColor(Rect(16, 16, 48, 48), Color::RED); + shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetCropWithResize_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // setCrop_legacy is applied immediately by default, with or without resize pending Transaction().setCrop_legacy(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); @@ -1265,7 +1579,7 @@ TEST_F(LayerTransactionTest, SetCropWithResize) { shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); { SCOPED_TRACE("resize applied"); auto shot = screenshot(); @@ -1274,10 +1588,34 @@ TEST_F(LayerTransactionTest, SetCropWithResize) { } } -TEST_F(LayerTransactionTest, SetCropWithNextResize) { +TEST_F(LayerTransactionTest, SetCropWithResize_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + // setCrop_legacy is applied immediately by default, with or without resize pending + Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); + { + SCOPED_TRACE("new buffer pending"); + auto shot = screenshot(); + shot->expectColor(Rect(8, 8, 16, 16), Color::RED); + shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 16, 16)); + { + SCOPED_TRACE("new buffer"); + auto shot = screenshot(); + shot->expectColor(Rect(8, 8, 16, 16), Color::RED); + shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK); + } +} + +TEST_F(LayerTransactionTest, SetCropWithNextResize_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // request setCrop_legacy to be applied with the next resize Transaction() @@ -1302,7 +1640,7 @@ TEST_F(LayerTransactionTest, SetCropWithNextResize) { } // finally resize - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); { SCOPED_TRACE("new crop applied"); auto shot = screenshot(); @@ -1311,10 +1649,45 @@ TEST_F(LayerTransactionTest, SetCropWithNextResize) { } } -TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow) { +TEST_F(LayerTransactionTest, SetCropWithNextResize_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + // request setCrop_legacy to be applied with the next resize + Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setGeometryAppliesWithResize(layer).apply(); + { + SCOPED_TRACE("set crop 1"); + screenshot()->expectColor(Rect(8, 8, 24, 24), Color::RED); + } + + Transaction().setCrop(layer, Rect(4, 4, 12, 12)).apply(); + { + SCOPED_TRACE("set crop 2"); + screenshot()->expectColor(Rect(4, 4, 12, 12), Color::RED); + } + + Transaction().setSize(layer, 16, 16).apply(); + { + SCOPED_TRACE("resize"); + screenshot()->expectColor(Rect(4, 4, 12, 12), Color::RED); + } + + // finally resize + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 16, 16)); + { + SCOPED_TRACE("new buffer"); + auto shot = screenshot(); + shot->expectColor(Rect(4, 4, 12, 12), Color::RED); + shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK); + } +} + +TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // setCrop_legacy is not immediate even with SCALE_TO_WINDOW override Transaction() @@ -1332,7 +1705,38 @@ TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow) { // XXX crop is never latched without other geometry change (b/69315677) Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply(); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); + Transaction().setPosition(layer, 0, 0).apply(); + { + SCOPED_TRACE("new crop applied"); + auto shot = screenshot(); + shot->expectColor(Rect(4, 4, 12, 12), Color::RED); + shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK); + } +} + +TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + // all properties are applied immediate so setGeometryAppliesWithResize has no effect + Transaction() + .setCrop(layer, Rect(4, 4, 12, 12)) + .setSize(layer, 16, 16) + .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) + .setGeometryAppliesWithResize(layer) + .apply(); + { + SCOPED_TRACE("new crop pending"); + auto shot = screenshot(); + shot->expectColor(Rect(4, 4, 12, 12), Color::RED); + shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK); + } + + Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply(); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 16, 16)); Transaction().setPosition(layer, 0, 0).apply(); { SCOPED_TRACE("new crop applied"); @@ -1342,10 +1746,10 @@ TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow) { } } -TEST_F(LayerTransactionTest, SetFinalCropBasic) { +TEST_F(LayerTransactionTest, SetFinalCropBasic_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); const Rect crop(8, 8, 24, 24); // same as in SetCropBasic @@ -1355,10 +1759,10 @@ TEST_F(LayerTransactionTest, SetFinalCropBasic) { shot->expectBorder(crop, Color::BLACK); } -TEST_F(LayerTransactionTest, SetFinalCropEmpty) { +TEST_F(LayerTransactionTest, SetFinalCropEmpty_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // same as in SetCropEmpty { @@ -1374,10 +1778,10 @@ TEST_F(LayerTransactionTest, SetFinalCropEmpty) { } } -TEST_F(LayerTransactionTest, SetFinalCropOutOfBounds) { +TEST_F(LayerTransactionTest, SetFinalCropOutOfBounds_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // same as in SetCropOutOfBounds Transaction().setFinalCrop_legacy(layer, Rect(-128, -64, 128, 64)).apply(); @@ -1386,10 +1790,10 @@ TEST_F(LayerTransactionTest, SetFinalCropOutOfBounds) { shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } -TEST_F(LayerTransactionTest, SetFinalCropWithTranslation) { +TEST_F(LayerTransactionTest, SetFinalCropWithTranslation_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // final crop is applied post-translation Transaction().setPosition(layer, 16, 16).setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)).apply(); @@ -1398,10 +1802,10 @@ TEST_F(LayerTransactionTest, SetFinalCropWithTranslation) { shot->expectBorder(Rect(16, 16, 24, 24), Color::BLACK); } -TEST_F(LayerTransactionTest, SetFinalCropWithScale) { +TEST_F(LayerTransactionTest, SetFinalCropWithScale_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // final crop is not affected by matrix Transaction() @@ -1413,10 +1817,10 @@ TEST_F(LayerTransactionTest, SetFinalCropWithScale) { shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK); } -TEST_F(LayerTransactionTest, SetFinalCropWithResize) { +TEST_F(LayerTransactionTest, SetFinalCropWithResize_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // same as in SetCropWithResize Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); @@ -1427,7 +1831,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithResize) { shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK); } - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); { SCOPED_TRACE("resize applied"); auto shot = screenshot(); @@ -1436,10 +1840,10 @@ TEST_F(LayerTransactionTest, SetFinalCropWithResize) { } } -TEST_F(LayerTransactionTest, SetFinalCropWithNextResize) { +TEST_F(LayerTransactionTest, SetFinalCropWithNextResize_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // same as in SetCropWithNextResize Transaction() @@ -1464,7 +1868,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResize) { } // finally resize - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); { SCOPED_TRACE("new final crop applied"); auto shot = screenshot(); @@ -1473,10 +1877,10 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResize) { } } -TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow) { +TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); // same as in SetCropWithNextResizeScaleToWindow Transaction() @@ -1494,7 +1898,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow) { // XXX final crop is never latched without other geometry change (b/69315677) Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply(); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); Transaction().setPosition(layer, 0, 0).apply(); { SCOPED_TRACE("new final crop applied"); @@ -1504,6 +1908,282 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow) { } } +TEST_F(LayerTransactionTest, SetBufferBasic_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetBufferMultipleBuffers_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + { + SCOPED_TRACE("set buffer 1"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32)); + + { + SCOPED_TRACE("set buffer 2"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + { + SCOPED_TRACE("set buffer 3"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + } +} + +TEST_F(LayerTransactionTest, SetBufferMultipleLayers_BufferState) { + sp layer1; + ASSERT_NO_FATAL_FAILURE( + layer1 = createLayer("test", 64, 64, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp layer2; + ASSERT_NO_FATAL_FAILURE( + layer2 = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::RED, 64, 64)); + + { + SCOPED_TRACE("set layer 1 buffer red"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 64, 64), Color::RED); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::BLUE, 32, 32)); + + { + SCOPED_TRACE("set layer 2 buffer blue"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectColor(Rect(0, 32, 64, 64), Color::RED); + shot->expectColor(Rect(0, 32, 32, 64), Color::RED); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::GREEN, 64, 64)); + { + SCOPED_TRACE("set layer 1 buffer green"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectColor(Rect(0, 32, 64, 64), Color::GREEN); + shot->expectColor(Rect(0, 32, 32, 64), Color::GREEN); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::WHITE, 32, 32)); + + { + SCOPED_TRACE("set layer 2 buffer white"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::WHITE); + shot->expectColor(Rect(0, 32, 64, 64), Color::GREEN); + shot->expectColor(Rect(0, 32, 32, 64), Color::GREEN); + } +} + +TEST_F(LayerTransactionTest, SetTransformRotate90_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE)); + + Transaction().setTransform(layer, NATIVE_WINDOW_TRANSFORM_ROT_90).apply(); + + screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::RED, Color::WHITE, + Color::GREEN, true /* filtered */); +} + +TEST_F(LayerTransactionTest, SetTransformFlipH_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE)); + + Transaction().setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_H).apply(); + + screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::GREEN, Color::RED, Color::WHITE, + Color::BLUE, true /* filtered */); +} + +TEST_F(LayerTransactionTest, SetTransformFlipV_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE)); + + Transaction().setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_V).apply(); + + screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::WHITE, Color::RED, + Color::GREEN, true /* filtered */); +} + +TEST_F(LayerTransactionTest, SetTransformToDisplayInverse_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + Transaction().setTransformToDisplayInverse(layer, false).apply(); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::GREEN, 32, 32)); + + Transaction().setTransformToDisplayInverse(layer, true).apply(); +} + +TEST_F(LayerTransactionTest, SetFenceBasic_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + sp fence = new Fence(-1); + + Transaction() + .setBuffer(layer, buffer) + .setAcquireFence(layer, fence) + .setSize(layer, 32, 32) + .apply(); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetDataspaceBasic_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + Transaction() + .setBuffer(layer, buffer) + .setDataspace(layer, ui::Dataspace::UNKNOWN) + .setSize(layer, 32, 32) + .apply(); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetHdrMetadataBasic_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + HdrMetadata hdrMetadata; + hdrMetadata.validTypes = 0; + Transaction() + .setBuffer(layer, buffer) + .setHdrMetadata(layer, hdrMetadata) + .setSize(layer, 32, 32) + .apply(); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetSurfaceDamageRegionBasic_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + Region region; + region.set(32, 32); + Transaction() + .setBuffer(layer, buffer) + .setSurfaceDamageRegion(layer, region) + .setSize(layer, 32, 32) + .apply(); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetApiBasic_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + Transaction() + .setBuffer(layer, buffer) + .setApi(layer, NATIVE_WINDOW_API_CPU) + .setSize(layer, 32, 32) + .apply(); + + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_F(LayerTransactionTest, SetSidebandStreamNull_BufferState) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + // verify this doesn't cause a crash + Transaction().setSidebandStream(layer, nullptr).apply(); +} + class LayerUpdateTest : public LayerTransactionTest { protected: virtual void SetUp() { @@ -2569,8 +3249,8 @@ TEST_F(ScreenCaptureTest, CaptureCrop) { mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30)); SurfaceComposerClient::Transaction() .setLayer(redLayer, INT32_MAX - 1) @@ -2603,8 +3283,8 @@ TEST_F(ScreenCaptureTest, CaptureSize) { mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30)); SurfaceComposerClient::Transaction() .setLayer(redLayer, INT32_MAX - 1) @@ -2636,7 +3316,7 @@ TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, PIXEL_FORMAT_RGBA_8888, 0); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); auto redLayerHandle = redLayer->getHandle(); mComposerClient->destroySurface(redLayerHandle); @@ -2655,9 +3335,9 @@ protected: void SetUp() override { LayerTransactionTest::SetUp(); bgLayer = createLayer("BG layer", 20, 20); - fillLayerColor(bgLayer, Color::RED); + fillBufferQueueLayerColor(bgLayer, Color::RED, 20, 20); fgLayer = createLayer("FG layer", 20, 20); - fillLayerColor(fgLayer, Color::BLUE); + fillBufferQueueLayerColor(fgLayer, Color::BLUE, 20, 20); Transaction().setLayer(fgLayer, mLayerZBase + 1).apply(); { SCOPED_TRACE("before anything"); -- cgit v1.2.3-59-g8ed1b From b8aaea16b889ef4859138cc528986551001f3add Mon Sep 17 00:00:00 2001 From: David Sodman Date: Thu, 14 Dec 2017 15:54:51 -0800 Subject: SF: use shared_ptr to track hwcLayer Use std::shared_ptr to track hwcLayer pointers. This is necessary because the calculation of data for HWComposer is done in Layer and the processing of that data is done in SurfaceFlinger, and we need to make sure that the hwcLayer is not destroyed by Layer while or before being used by SurfaceFlinger. Bug: 112259502 Test: cts -m CtsViewTestCases SurfaceFlinger_test vrflinger_test Change-Id: I683dd071efbeebd9a9941053183daf4efb88469e --- services/surfaceflinger/Layer.cpp | 19 ++++++++++--------- services/surfaceflinger/Layer.h | 2 +- services/surfaceflinger/LayerBE.cpp | 2 +- services/surfaceflinger/LayerBE.h | 4 ++-- 4 files changed, 14 insertions(+), 13 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index ee9ee78fae..fef53bb452 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -230,7 +230,10 @@ sp Layer::getHandle() { bool Layer::createHwcLayer(HWComposer* hwc, int32_t displayId) { LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(displayId) != 0, "Already have a layer for display %d", displayId); - HWC2::Layer* layer = hwc->createLayer(displayId); + auto layer = std::shared_ptr( + hwc->createLayer(displayId), + [hwc, displayId](HWC2::Layer* layer) { + hwc->destroyLayer(displayId, layer); }); if (!layer) { return false; } @@ -249,11 +252,8 @@ bool Layer::destroyHwcLayer(int32_t displayId) { auto& hwcInfo = getBE().mHwcLayers[displayId]; LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr, "Attempt to destroy null layer"); LOG_ALWAYS_FATAL_IF(hwcInfo.hwc == nullptr, "Missing HWComposer"); - hwcInfo.hwc->destroyLayer(displayId, hwcInfo.layer); - // The layer destroyed listener should have cleared the entry from - // mHwcLayers. Verify that. - LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(displayId) != 0, - "Stale layer entry in getBE().mHwcLayers"); + hwcInfo.layer = nullptr; + return true; } @@ -716,7 +716,8 @@ void Layer::updateCursorPosition(const sp& display) { auto position = displayTransform.transform(frame); auto error = - getBE().mHwcLayers[displayId].layer->setCursorPosition(position.left, position.top); + (getBE().mHwcLayers[displayId].layer)->setCursorPosition( + position.left, position.top); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set cursor position " "to (%d, %d): %s (%d)", @@ -759,13 +760,13 @@ void Layer::setCompositionType(int32_t displayId, HWC2::Composition type, bool c } auto& hwcInfo = getBE().mHwcLayers[displayId]; auto& hwcLayer = hwcInfo.layer; - ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(), to_string(type).c_str(), + ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", (hwcLayer)->getId(), to_string(type).c_str(), static_cast(callIntoHwc)); if (hwcInfo.compositionType != type) { ALOGV(" actually setting"); hwcInfo.compositionType = type; if (callIntoHwc) { - auto error = hwcLayer->setCompositionType(type); + auto error = (hwcLayer)->setCompositionType(type); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set " "composition type %s: %s (%d)", diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index a48cdffd8b..a6da495579 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -510,7 +510,7 @@ public: if (getBE().mHwcLayers.count(displayId) == 0) { return nullptr; } - return getBE().mHwcLayers[displayId].layer; + return getBE().mHwcLayers[displayId].layer.get(); } // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp index 51b615b586..eea4ebda59 100644 --- a/services/surfaceflinger/LayerBE.cpp +++ b/services/surfaceflinger/LayerBE.cpp @@ -35,7 +35,7 @@ void LayerBE::onLayerDisplayed(const sp& releaseFence) { } void CompositionInfo::dumpHwc(const char* tag) const { - ALOGV("[%s]\thwcLayer=%p", tag, hwc.hwcLayer); + ALOGV("[%s]\thwcLayer=%p", tag, hwc.hwcLayer.get()); ALOGV("[%s]\tfence=%p", tag, hwc.fence.get()); ALOGV("[%s]\ttransform=%d", tag, hwc.transform); ALOGV("[%s]\tz=%d", tag, hwc.z); diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index b5acebafb1..14af380c14 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -39,7 +39,7 @@ struct CompositionInfo { int mBufferSlot = BufferQueue::INVALID_BUFFER_SLOT; LayerBE* layer = nullptr; struct { - HWC2::Layer* hwcLayer; + std::shared_ptr hwcLayer; sp fence; HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid; Rect displayFrame; @@ -103,7 +103,7 @@ private: transform(HWC2::Transform::None) {} HWComposer* hwc; - HWC2::Layer* layer; + std::shared_ptr layer; bool forceClientComposition; HWC2::Composition compositionType; bool clearClientTarget; -- cgit v1.2.3-59-g8ed1b From bd6480f7d078f26f432d903007f3f05d3fc1590f Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Fri, 10 Aug 2018 14:37:31 +0200 Subject: Avoid calling into HWC in onFirstRef The information is already available - no need to call into HWC. This saved around 150-200us per onFirstRef call. Test: atest UiAutomationTest#testWindowContentFrameStats Test: PerfTransitionTest Test: LayerTypeTransactionTest#RefreshRateIsInitialized Bug: 112352758 Change-Id: I406754d33d53d6c60e354f5a403f1d5568f714c4 --- services/surfaceflinger/Layer.cpp | 17 +---------------- services/surfaceflinger/Layer.h | 2 -- 2 files changed, 1 insertion(+), 18 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index ee9ee78fae..d9978b8659 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -132,22 +132,7 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n CompositorTiming compositorTiming; flinger->getCompositorTiming(&compositorTiming); mFrameEventHistory.initializeCompositorTiming(compositorTiming); -} - -void Layer::onFirstRef() NO_THREAD_SAFETY_ANALYSIS { - if (!isCreatedFromMainThread()) { - // Grab the SF state lock during this since it's the only way to safely access HWC - mFlinger->mStateLock.lock(); - } - - const auto& hwc = mFlinger->getHwComposer(); - const auto& activeConfig = hwc.getActiveConfig(HWC_DISPLAY_PRIMARY); - nsecs_t displayPeriod = activeConfig->getVsyncPeriod(); - mFrameTracker.setDisplayRefreshPeriod(displayPeriod); - - if (!isCreatedFromMainThread()) { - mFlinger->mStateLock.unlock(); - } + mFrameTracker.setDisplayRefreshPeriod(compositorTiming.interval); } Layer::~Layer() { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index a48cdffd8b..24a8bdebb7 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -604,8 +604,6 @@ protected: : mFlinger(flinger), mLayer(layer) {} }; - virtual void onFirstRef(); - friend class impl::SurfaceInterceptor; void commitTransaction(const State& stateToCommit); -- cgit v1.2.3-59-g8ed1b From 3db423465dc6e177aab27f315426541714201ebe Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Thu, 16 Aug 2018 09:15:59 -0700 Subject: [SurfaceFlinger] Remove unused clz.h The built-in method clz is no longer used anywhere in SurfaceFlinger, thus remove this file and change all usage of min/max/swap to standard methods. BUG: 112585051 Test: Build, flash Change-Id: Ia5b47afae1ecbbda3c60d19de62ff9c76db743a4 --- services/surfaceflinger/BufferLayer.cpp | 1 - services/surfaceflinger/BufferQueueLayer.cpp | 3 +- services/surfaceflinger/BufferStateLayer.cpp | 5 +-- services/surfaceflinger/DisplayDevice.cpp | 3 +- services/surfaceflinger/Layer.cpp | 1 - services/surfaceflinger/LayerRejecter.cpp | 6 +-- services/surfaceflinger/SurfaceFlinger.cpp | 1 - services/surfaceflinger/Transform.cpp | 27 ++++++------ services/surfaceflinger/clz.h | 64 ---------------------------- 9 files changed, 19 insertions(+), 92 deletions(-) delete mode 100644 services/surfaceflinger/clz.h (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index e7246665dd..2c91da060a 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -23,7 +23,6 @@ #include "Colorizer.h" #include "DisplayDevice.h" #include "LayerRejecter.h" -#include "clz.h" #include "RenderEngine/RenderEngine.h" diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 6c339b78a9..6dd29ba316 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -16,7 +16,6 @@ #include "BufferQueueLayer.h" #include "LayerRejecter.h" -#include "clz.h" #include @@ -449,7 +448,7 @@ void BufferQueueLayer::onFirstRef() { status_t BufferQueueLayer::setDefaultBufferProperties(uint32_t w, uint32_t h, PixelFormat format) { uint32_t const maxSurfaceDims = - min(mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims()); + std::min(mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims()); // never allow a surface larger than what our underlying GL implementation // can handle. diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 44fa760ec5..276e0e1d63 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -21,7 +21,6 @@ #include "BufferStateLayer.h" #include "RenderEngine/Image.h" -#include "clz.h" #include @@ -401,13 +400,13 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse uint32_t bufferHeight = s.buffer->height; if (s.transform & Transform::ROT_90) { - swap(bufferWidth, bufferHeight); + std::swap(bufferWidth, bufferHeight); } if (s.transformToDisplayInverse) { uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); if (invTransform & Transform::ROT_90) { - swap(bufferWidth, bufferHeight); + std::swap(bufferWidth, bufferHeight); } } diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 4d2b0eacaa..54c0dbee74 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -44,7 +44,6 @@ #include "DisplayHardware/HWC2.h" #include "RenderEngine/RenderEngine.h" -#include "clz.h" #include "DisplayDevice.h" #include "SurfaceFlinger.h" #include "Layer.h" @@ -582,7 +581,7 @@ void DisplayDevice::setProjection(int orientation, if (R.getOrientation() & Transform::ROT_90) { // viewport is always specified in the logical orientation // of the display (ie: post-rotation). - swap(viewport.right, viewport.bottom); + std::swap(viewport.right, viewport.bottom); } } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 2a070744bc..35cbda061d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -50,7 +50,6 @@ #include "LayerRejecter.h" #include "MonitoredProducer.h" #include "SurfaceFlinger.h" -#include "clz.h" #include "DisplayHardware/HWComposer.h" diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp index 70558d4cc8..bd59d17ac2 100644 --- a/services/surfaceflinger/LayerRejecter.cpp +++ b/services/surfaceflinger/LayerRejecter.cpp @@ -19,8 +19,6 @@ #include #include -#include "clz.h" - #define DEBUG_RESIZE 0 namespace android { @@ -53,13 +51,13 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) // check that we received a buffer of the right size // (Take the buffer's orientation into account) if (item.mTransform & Transform::ROT_90) { - swap(bufWidth, bufHeight); + std::swap(bufWidth, bufHeight); } if (mTransformToDisplayInverse) { uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); if (invTransform & Transform::ROT_90) { - swap(bufWidth, bufHeight); + std::swap(bufWidth, bufHeight); } } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 41c7f22bc7..0e88fa0a72 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -75,7 +75,6 @@ #include "LayerVector.h" #include "MonitoredProducer.h" #include "SurfaceFlinger.h" -#include "clz.h" #include "DisplayHardware/ComposerHal.h" #include "DisplayHardware/DisplayIdentification.h" diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp index e05ed5375e..bc9e5cd5d7 100644 --- a/services/surfaceflinger/Transform.cpp +++ b/services/surfaceflinger/Transform.cpp @@ -21,7 +21,6 @@ #include #include "Transform.h" -#include "clz.h" // --------------------------------------------------------------------------- @@ -137,7 +136,7 @@ status_t Transform::set(uint32_t flags, float w, float h) Transform H, V, R; if (flags & ROT_90) { // w & h are inverted when rotating by 90 degrees - swap(w, h); + std::swap(w, h); } if (flags & FLIP_H) { @@ -210,15 +209,15 @@ Rect Transform::transform(const Rect& bounds, bool roundOutwards) const rb = transform(rb); if (roundOutwards) { - r.left = floorf(min(lt[0], rt[0], lb[0], rb[0])); - r.top = floorf(min(lt[1], rt[1], lb[1], rb[1])); - r.right = ceilf(max(lt[0], rt[0], lb[0], rb[0])); - r.bottom = ceilf(max(lt[1], rt[1], lb[1], rb[1])); + r.left = floorf(std::min({lt[0], rt[0], lb[0], rb[0]})); + r.top = floorf(std::min({lt[1], rt[1], lb[1], rb[1]})); + r.right = ceilf(std::max({lt[0], rt[0], lb[0], rb[0]})); + r.bottom = ceilf(std::max({lt[1], rt[1], lb[1], rb[1]})); } else { - r.left = floorf(min(lt[0], rt[0], lb[0], rb[0]) + 0.5f); - r.top = floorf(min(lt[1], rt[1], lb[1], rb[1]) + 0.5f); - r.right = floorf(max(lt[0], rt[0], lb[0], rb[0]) + 0.5f); - r.bottom = floorf(max(lt[1], rt[1], lb[1], rb[1]) + 0.5f); + r.left = floorf(std::min({lt[0], rt[0], lb[0], rb[0]}) + 0.5f); + r.top = floorf(std::min({lt[1], rt[1], lb[1], rb[1]}) + 0.5f); + r.right = floorf(std::max({lt[0], rt[0], lb[0], rb[0]}) + 0.5f); + r.bottom = floorf(std::max({lt[1], rt[1], lb[1], rb[1]}) + 0.5f); } return r; @@ -237,10 +236,10 @@ FloatRect Transform::transform(const FloatRect& bounds) const rb = transform(rb); FloatRect r; - r.left = min(lt[0], rt[0], lb[0], rb[0]); - r.top = min(lt[1], rt[1], lb[1], rb[1]); - r.right = max(lt[0], rt[0], lb[0], rb[0]); - r.bottom = max(lt[1], rt[1], lb[1], rb[1]); + r.left = std::min({lt[0], rt[0], lb[0], rb[0]}); + r.top = std::min({lt[1], rt[1], lb[1], rb[1]}); + r.right = std::max({lt[0], rt[0], lb[0], rb[0]}); + r.bottom = std::max({lt[1], rt[1], lb[1], rb[1]}); return r; } diff --git a/services/surfaceflinger/clz.h b/services/surfaceflinger/clz.h deleted file mode 100644 index a4c5262ddf..0000000000 --- a/services/surfaceflinger/clz.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#ifndef ANDROID_SURFACE_FLINGER_CLZ_H - -#include - -namespace android { - -int inline clz(int32_t x) { - return __builtin_clz(x); -} - -template -static inline T min(T a, T b) { - return a -static inline T min(T a, T b, T c) { - return min(a, min(b, c)); -} -template -static inline T min(T a, T b, T c, T d) { - return min(a, b, min(c, d)); -} - -template -static inline T max(T a, T b) { - return a>b ? a : b; -} -template -static inline T max(T a, T b, T c) { - return max(a, max(b, c)); -} -template -static inline T max(T a, T b, T c, T d) { - return max(a, b, max(c, d)); -} - -template -static inline -void swap(T& a, T& b) { - T t(a); - a = b; - b = t; -} - - -}; // namespace android - -#endif /* ANDROID_SURFACE_FLINGER_CLZ_H */ -- cgit v1.2.3-59-g8ed1b From efefaac7748a7c2d1f5878f398c1d6c38713ce03 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Fri, 17 Aug 2018 12:27:51 -0700 Subject: [SurfaceFlinger] Move Transform to libs/ui A bunch of code in SurfaceFlinger uses Transform, so does RenderEngine. In order to move RenderEngine to its own library, we need to lift Transform to another place where it's part of VNDK. Since Transform depends on libs/ui, we move Transform to libs/ui as well. BUG: 112585051 Test: Build, flash, boot and check transformation. Change-Id: Ie4d13ee135ba3f71fcbd9f86994a0b048e2c6878 --- libs/ui/Android.bp | 1 + libs/ui/Transform.cpp | 416 ++++++++++++++++++++ libs/ui/include/ui/Transform.h | 113 ++++++ services/surfaceflinger/Android.bp | 1 - services/surfaceflinger/BufferLayer.cpp | 4 +- services/surfaceflinger/BufferLayer.h | 1 - services/surfaceflinger/BufferStateLayer.cpp | 6 +- services/surfaceflinger/BufferStateLayer.h | 2 +- services/surfaceflinger/ColorLayer.cpp | 2 +- services/surfaceflinger/DisplayDevice.cpp | 40 +- services/surfaceflinger/DisplayDevice.h | 22 +- services/surfaceflinger/Layer.cpp | 47 +-- services/surfaceflinger/Layer.h | 10 +- services/surfaceflinger/LayerProtoHelper.cpp | 3 +- services/surfaceflinger/LayerProtoHelper.h | 8 +- services/surfaceflinger/LayerRejecter.cpp | 4 +- services/surfaceflinger/RenderArea.cpp | 23 +- services/surfaceflinger/RenderArea.h | 15 +- .../surfaceflinger/RenderEngine/Description.cpp | 3 - .../RenderEngine/GLES20RenderEngine.cpp | 10 +- .../RenderEngine/GLES20RenderEngine.h | 3 +- .../surfaceflinger/RenderEngine/RenderEngine.h | 5 +- services/surfaceflinger/RenderEngine/Surface.cpp | 1 + services/surfaceflinger/SurfaceFlinger.cpp | 38 +- services/surfaceflinger/Transform.cpp | 430 --------------------- services/surfaceflinger/Transform.h | 118 ------ .../unittests/mock/RenderEngine/MockRenderEngine.h | 2 +- 27 files changed, 661 insertions(+), 667 deletions(-) create mode 100644 libs/ui/Transform.cpp create mode 100644 libs/ui/include/ui/Transform.h delete mode 100644 services/surfaceflinger/Transform.cpp delete mode 100644 services/surfaceflinger/Transform.h (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp index d25ad1a46d..e3ef2a9e1d 100644 --- a/libs/ui/Android.bp +++ b/libs/ui/Android.bp @@ -65,6 +65,7 @@ cc_library_shared { "PixelFormat.cpp", "Rect.cpp", "Region.cpp", + "Transform.cpp", "UiConfig.cpp", ], diff --git a/libs/ui/Transform.cpp b/libs/ui/Transform.cpp new file mode 100644 index 0000000000..8e949ec880 --- /dev/null +++ b/libs/ui/Transform.cpp @@ -0,0 +1,416 @@ +/* + * Copyright (C) 2007 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. + */ + +#include + +#include +#include +#include +#include + +namespace android { +namespace ui { + +Transform::Transform() { + reset(); +} + +Transform::Transform(const Transform& other) + : mMatrix(other.mMatrix), mType(other.mType) { +} + +Transform::Transform(uint32_t orientation) { + set(orientation, 0, 0); +} + +Transform::~Transform() = default; + +static const float EPSILON = 0.0f; + +bool Transform::isZero(float f) { + return fabs(f) <= EPSILON; +} + +bool Transform::absIsOne(float f) { + return isZero(fabs(f) - 1.0f); +} + +Transform Transform::operator * (const Transform& rhs) const +{ + if (CC_LIKELY(mType == IDENTITY)) + return rhs; + + Transform r(*this); + if (rhs.mType == IDENTITY) + return r; + + // TODO: we could use mType to optimize the matrix multiply + const mat33& A(mMatrix); + const mat33& B(rhs.mMatrix); + mat33& D(r.mMatrix); + for (size_t i = 0; i < 3; i++) { + const float v0 = A[0][i]; + const float v1 = A[1][i]; + const float v2 = A[2][i]; + D[0][i] = v0*B[0][0] + v1*B[0][1] + v2*B[0][2]; + D[1][i] = v0*B[1][0] + v1*B[1][1] + v2*B[1][2]; + D[2][i] = v0*B[2][0] + v1*B[2][1] + v2*B[2][2]; + } + r.mType |= rhs.mType; + + // TODO: we could recompute this value from r and rhs + r.mType &= 0xFF; + r.mType |= UNKNOWN_TYPE; + return r; +} + +Transform& Transform::operator=(const Transform& other) { + mMatrix = other.mMatrix; + mType = other.mType; + return *this; +} + +const vec3& Transform::operator [] (size_t i) const { + return mMatrix[i]; +} + +float Transform::tx() const { + return mMatrix[2][0]; +} + +float Transform::ty() const { + return mMatrix[2][1]; +} + +void Transform::reset() { + mType = IDENTITY; + for(size_t i = 0; i < 3; i++) { + vec3& v(mMatrix[i]); + for (size_t j = 0; j < 3; j++) + v[j] = ((i == j) ? 1.0f : 0.0f); + } +} + +void Transform::set(float tx, float ty) +{ + mMatrix[2][0] = tx; + mMatrix[2][1] = ty; + mMatrix[2][2] = 1.0f; + + if (isZero(tx) && isZero(ty)) { + mType &= ~TRANSLATE; + } else { + mType |= TRANSLATE; + } +} + +void Transform::set(float a, float b, float c, float d) +{ + mat33& M(mMatrix); + M[0][0] = a; M[1][0] = b; + M[0][1] = c; M[1][1] = d; + M[0][2] = 0; M[1][2] = 0; + mType = UNKNOWN_TYPE; +} + +status_t Transform::set(uint32_t flags, float w, float h) +{ + if (flags & ROT_INVALID) { + // that's not allowed! + reset(); + return BAD_VALUE; + } + + Transform H, V, R; + if (flags & ROT_90) { + // w & h are inverted when rotating by 90 degrees + std::swap(w, h); + } + + if (flags & FLIP_H) { + H.mType = (FLIP_H << 8) | SCALE; + H.mType |= isZero(w) ? IDENTITY : TRANSLATE; + mat33& M(H.mMatrix); + M[0][0] = -1; + M[2][0] = w; + } + + if (flags & FLIP_V) { + V.mType = (FLIP_V << 8) | SCALE; + V.mType |= isZero(h) ? IDENTITY : TRANSLATE; + mat33& M(V.mMatrix); + M[1][1] = -1; + M[2][1] = h; + } + + if (flags & ROT_90) { + const float original_w = h; + R.mType = (ROT_90 << 8) | ROTATE; + R.mType |= isZero(original_w) ? IDENTITY : TRANSLATE; + mat33& M(R.mMatrix); + M[0][0] = 0; M[1][0] =-1; M[2][0] = original_w; + M[0][1] = 1; M[1][1] = 0; + } + + *this = (R*(H*V)); + return NO_ERROR; +} + +vec2 Transform::transform(const vec2& v) const { + vec2 r; + const mat33& M(mMatrix); + r[0] = M[0][0]*v[0] + M[1][0]*v[1] + M[2][0]; + r[1] = M[0][1]*v[0] + M[1][1]*v[1] + M[2][1]; + return r; +} + +vec3 Transform::transform(const vec3& v) const { + vec3 r; + const mat33& M(mMatrix); + r[0] = M[0][0]*v[0] + M[1][0]*v[1] + M[2][0]*v[2]; + r[1] = M[0][1]*v[0] + M[1][1]*v[1] + M[2][1]*v[2]; + r[2] = M[0][2]*v[0] + M[1][2]*v[1] + M[2][2]*v[2]; + return r; +} + +vec2 Transform::transform(int x, int y) const +{ + return transform(vec2(x,y)); +} + +Rect Transform::makeBounds(int w, int h) const +{ + return transform( Rect(w, h) ); +} + +Rect Transform::transform(const Rect& bounds, bool roundOutwards) const +{ + Rect r; + vec2 lt( bounds.left, bounds.top ); + vec2 rt( bounds.right, bounds.top ); + vec2 lb( bounds.left, bounds.bottom ); + vec2 rb( bounds.right, bounds.bottom ); + + lt = transform(lt); + rt = transform(rt); + lb = transform(lb); + rb = transform(rb); + + if (roundOutwards) { + r.left = static_cast(floorf(std::min({lt[0], rt[0], lb[0], rb[0]}))); + r.top = static_cast(floorf(std::min({lt[1], rt[1], lb[1], rb[1]}))); + r.right = static_cast(ceilf(std::max({lt[0], rt[0], lb[0], rb[0]}))); + r.bottom = static_cast(ceilf(std::max({lt[1], rt[1], lb[1], rb[1]}))); + } else { + r.left = static_cast(floorf(std::min({lt[0], rt[0], lb[0], rb[0]}) + 0.5f)); + r.top = static_cast(floorf(std::min({lt[1], rt[1], lb[1], rb[1]}) + 0.5f)); + r.right = static_cast(floorf(std::max({lt[0], rt[0], lb[0], rb[0]}) + 0.5f)); + r.bottom = static_cast(floorf(std::max({lt[1], rt[1], lb[1], rb[1]}) + 0.5f)); + } + + return r; +} + +FloatRect Transform::transform(const FloatRect& bounds) const +{ + vec2 lt(bounds.left, bounds.top); + vec2 rt(bounds.right, bounds.top); + vec2 lb(bounds.left, bounds.bottom); + vec2 rb(bounds.right, bounds.bottom); + + lt = transform(lt); + rt = transform(rt); + lb = transform(lb); + rb = transform(rb); + + FloatRect r; + r.left = std::min({lt[0], rt[0], lb[0], rb[0]}); + r.top = std::min({lt[1], rt[1], lb[1], rb[1]}); + r.right = std::max({lt[0], rt[0], lb[0], rb[0]}); + r.bottom = std::max({lt[1], rt[1], lb[1], rb[1]}); + + return r; +} + +Region Transform::transform(const Region& reg) const +{ + Region out; + if (CC_UNLIKELY(type() > TRANSLATE)) { + if (CC_LIKELY(preserveRects())) { + Region::const_iterator it = reg.begin(); + Region::const_iterator const end = reg.end(); + while (it != end) { + out.orSelf(transform(*it++)); + } + } else { + out.set(transform(reg.bounds())); + } + } else { + int xpos = static_cast(floorf(tx() + 0.5f)); + int ypos = static_cast(floorf(ty() + 0.5f)); + out = reg.translate(xpos, ypos); + } + return out; +} + +uint32_t Transform::type() const +{ + if (mType & UNKNOWN_TYPE) { + // recompute what this transform is + + const mat33& M(mMatrix); + const float a = M[0][0]; + const float b = M[1][0]; + const float c = M[0][1]; + const float d = M[1][1]; + const float x = M[2][0]; + const float y = M[2][1]; + + bool scale = false; + uint32_t flags = ROT_0; + if (isZero(b) && isZero(c)) { + if (a<0) flags |= FLIP_H; + if (d<0) flags |= FLIP_V; + if (!absIsOne(a) || !absIsOne(d)) { + scale = true; + } + } else if (isZero(a) && isZero(d)) { + flags |= ROT_90; + if (b>0) flags |= FLIP_V; + if (c<0) flags |= FLIP_H; + if (!absIsOne(b) || !absIsOne(c)) { + scale = true; + } + } else { + // there is a skew component and/or a non 90 degrees rotation + flags = ROT_INVALID; + } + + mType = flags << 8; + if (flags & ROT_INVALID) { + mType |= UNKNOWN; + } else { + if ((flags & ROT_90) || ((flags & ROT_180) == ROT_180)) + mType |= ROTATE; + if (flags & FLIP_H) + mType ^= SCALE; + if (flags & FLIP_V) + mType ^= SCALE; + if (scale) + mType |= SCALE; + } + + if (!isZero(x) || !isZero(y)) + mType |= TRANSLATE; + } + return mType; +} + +Transform Transform::inverse() const { + // our 3x3 matrix is always of the form of a 2x2 transformation + // followed by a translation: T*M, therefore: + // (T*M)^-1 = M^-1 * T^-1 + Transform result; + if (mType <= TRANSLATE) { + // 1 0 0 + // 0 1 0 + // x y 1 + result = *this; + result.mMatrix[2][0] = -result.mMatrix[2][0]; + result.mMatrix[2][1] = -result.mMatrix[2][1]; + } else { + // a c 0 + // b d 0 + // x y 1 + const mat33& M(mMatrix); + const float a = M[0][0]; + const float b = M[1][0]; + const float c = M[0][1]; + const float d = M[1][1]; + const float x = M[2][0]; + const float y = M[2][1]; + + const float idet = 1.0f / (a*d - b*c); + result.mMatrix[0][0] = d*idet; + result.mMatrix[0][1] = -c*idet; + result.mMatrix[1][0] = -b*idet; + result.mMatrix[1][1] = a*idet; + result.mType = mType; + + vec2 T(-x, -y); + T = result.transform(T); + result.mMatrix[2][0] = T[0]; + result.mMatrix[2][1] = T[1]; + } + return result; +} + +uint32_t Transform::getType() const { + return type() & 0xFF; +} + +uint32_t Transform::getOrientation() const +{ + return (type() >> 8) & 0xFF; +} + +bool Transform::preserveRects() const +{ + return (getOrientation() & ROT_INVALID) ? false : true; +} + +void Transform::dump(const char* name) const +{ + type(); // updates the type + + String8 flags, type; + const mat33& m(mMatrix); + uint32_t orient = mType >> 8; + + if (orient&ROT_INVALID) { + flags.append("ROT_INVALID "); + } else { + if (orient&ROT_90) { + flags.append("ROT_90 "); + } else { + flags.append("ROT_0 "); + } + if (orient&FLIP_V) + flags.append("FLIP_V "); + if (orient&FLIP_H) + flags.append("FLIP_H "); + } + + if (!(mType&(SCALE|ROTATE|TRANSLATE))) + type.append("IDENTITY "); + if (mType&SCALE) + type.append("SCALE "); + if (mType&ROTATE) + type.append("ROTATE "); + if (mType&TRANSLATE) + type.append("TRANSLATE "); + + ALOGD("%s 0x%08x (%s, %s)", name, mType, flags.string(), type.string()); + ALOGD("%.4f %.4f %.4f", static_cast(m[0][0]), static_cast(m[1][0]), + static_cast(m[2][0])); + ALOGD("%.4f %.4f %.4f", static_cast(m[0][1]), static_cast(m[1][1]), + static_cast(m[2][1])); + ALOGD("%.4f %.4f %.4f", static_cast(m[0][2]), static_cast(m[1][2]), + static_cast(m[2][2])); +} + +} // namespace ui +} // namespace android diff --git a/libs/ui/include/ui/Transform.h b/libs/ui/include/ui/Transform.h new file mode 100644 index 0000000000..42dca75f6b --- /dev/null +++ b/libs/ui/include/ui/Transform.h @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2007 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. + */ + +#ifndef ANDROID_TRANSFORM_H +#define ANDROID_TRANSFORM_H + +#include +#include + +#include +#include +#include +#include +#include + +namespace android { + +class Region; + +namespace ui { + +class Transform { +public: + Transform(); + Transform(const Transform& other); + explicit Transform(uint32_t orientation); + ~Transform(); + + enum orientation_flags { + ROT_0 = 0x00000000, + FLIP_H = HAL_TRANSFORM_FLIP_H, + FLIP_V = HAL_TRANSFORM_FLIP_V, + ROT_90 = HAL_TRANSFORM_ROT_90, + ROT_180 = FLIP_H|FLIP_V, + ROT_270 = ROT_180|ROT_90, + ROT_INVALID = 0x80 + }; + + enum type_mask : uint32_t { + IDENTITY = 0, + TRANSLATE = 0x1, + ROTATE = 0x2, + SCALE = 0x4, + UNKNOWN = 0x8 + }; + + // query the transform + bool preserveRects() const; + uint32_t getType() const; + uint32_t getOrientation() const; + + const vec3& operator [] (size_t i) const; // returns column i + float tx() const; + float ty() const; + + // modify the transform + void reset(); + void set(float tx, float ty); + void set(float a, float b, float c, float d); + status_t set(uint32_t flags, float w, float h); + + // transform data + Rect makeBounds(int w, int h) const; + vec2 transform(int x, int y) const; + Region transform(const Region& reg) const; + Rect transform(const Rect& bounds, + bool roundOutwards = false) const; + FloatRect transform(const FloatRect& bounds) const; + Transform& operator = (const Transform& other); + Transform operator * (const Transform& rhs) const; + // assumes the last row is < 0 , 0 , 1 > + vec2 transform(const vec2& v) const; + vec3 transform(const vec3& v) const; + + Transform inverse() const; + + // for debugging + void dump(const char* name) const; + +private: + struct mat33 { + vec3 v[3]; + inline const vec3& operator [] (size_t i) const { return v[i]; } + inline vec3& operator [] (size_t i) { return v[i]; } + }; + + enum { UNKNOWN_TYPE = 0x80000000 }; + + uint32_t type() const; + static bool absIsOne(float f); + static bool isZero(float f); + + mat33 mMatrix; + mutable uint32_t mType; +}; + +} // namespace ui +} // namespace android + +#endif /* ANDROID_TRANSFORM_H */ diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index fa0141f48b..efaeaa2d73 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -137,7 +137,6 @@ filegroup { "SurfaceInterceptor.cpp", "SurfaceTracing.cpp", "TimeStats/TimeStats.cpp", - "Transform.cpp", ], } diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 2c91da060a..e1094d828a 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -258,7 +258,7 @@ bool BufferLayer::isHdrY410() const { void BufferLayer::setPerFrameData(const sp& display) { // Apply this display's projection's viewport to the visible region // before giving it to the HWC HAL. - const Transform& tr = display->getTransform(); + const ui::Transform& tr = display->getTransform(); const auto& viewport = display->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); const auto displayId = display->getId(); @@ -638,7 +638,7 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT */ const Rect bounds{computeBounds()}; // Rounds from FloatRect - Transform t = getTransform(); + ui::Transform t = getTransform(); Rect win = bounds; Rect finalCrop = getFinalCrop(s); if (!finalCrop.isEmpty()) { diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 13f4e83b44..0b641b731f 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -27,7 +27,6 @@ #include "RenderEngine/Mesh.h" #include "RenderEngine/Texture.h" #include "SurfaceFlinger.h" -#include "Transform.h" #include #include diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 276e0e1d63..369ad89e53 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -213,7 +213,7 @@ bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) { bool BufferStateLayer::setMatrix(const layer_state_t::matrix22_t& matrix, bool allowNonRectPreservingTransforms) { - Transform t; + ui::Transform t; t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); if (!allowNonRectPreservingTransforms && !t.preserveRects()) { @@ -399,13 +399,13 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse uint32_t bufferWidth = s.buffer->width; uint32_t bufferHeight = s.buffer->height; - if (s.transform & Transform::ROT_90) { + if (s.transform & ui::Transform::ROT_90) { std::swap(bufferWidth, bufferHeight); } if (s.transformToDisplayInverse) { uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); - if (invTransform & Transform::ROT_90) { + if (invTransform & ui::Transform::ROT_90) { std::swap(bufferWidth, bufferHeight); } } diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 4d7396ef81..e492375837 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -52,7 +52,7 @@ public: uint32_t getActiveWidth(const Layer::State& s) const override { return s.active.w; } uint32_t getActiveHeight(const Layer::State& s) const override { return s.active.h; } - Transform getActiveTransform(const Layer::State& s) const override { + ui::Transform getActiveTransform(const Layer::State& s) const override { return s.active.transform; } Region getActiveTransparentRegion(const Layer::State& s) const override { diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index bac46a38b4..7eeaabb886 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -72,7 +72,7 @@ bool ColorLayer::isVisible() const { } void ColorLayer::setPerFrameData(const sp& display) { - const Transform& tr = display->getTransform(); + const ui::Transform& tr = display->getTransform(); const auto& viewport = display->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); const auto displayId = display->getId(); diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 54c0dbee74..776b84ae0b 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -389,7 +389,7 @@ void DisplayDevice::setViewportAndProjection() const { size_t h = mDisplayHeight; Rect sourceCrop(0, 0, w, h); mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, h, - false, Transform::ROT_0); + false, ui::Transform::ROT_0); } const sp& DisplayDevice::getClientTargetAcquireFence() const { @@ -419,7 +419,7 @@ Region DisplayDevice::getDirtyRegion(bool repaintEverything) const { if (repaintEverything) { dirty.set(getBounds()); } else { - const Transform& planeTransform(mGlobalTransform); + const ui::Transform& planeTransform(mGlobalTransform); dirty = planeTransform.transform(this->dirtyRegion); dirty.andSelf(getBounds()); } @@ -498,37 +498,37 @@ uint32_t DisplayDevice::getOrientationTransform() const { uint32_t transform = 0; switch (mOrientation) { case DisplayState::eOrientationDefault: - transform = Transform::ROT_0; + transform = ui::Transform::ROT_0; break; case DisplayState::eOrientation90: - transform = Transform::ROT_90; + transform = ui::Transform::ROT_90; break; case DisplayState::eOrientation180: - transform = Transform::ROT_180; + transform = ui::Transform::ROT_180; break; case DisplayState::eOrientation270: - transform = Transform::ROT_270; + transform = ui::Transform::ROT_270; break; } return transform; } status_t DisplayDevice::orientationToTransfrom( - int orientation, int w, int h, Transform* tr) + int orientation, int w, int h, ui::Transform* tr) { uint32_t flags = 0; switch (orientation) { case DisplayState::eOrientationDefault: - flags = Transform::ROT_0; + flags = ui::Transform::ROT_0; break; case DisplayState::eOrientation90: - flags = Transform::ROT_90; + flags = ui::Transform::ROT_90; break; case DisplayState::eOrientation180: - flags = Transform::ROT_180; + flags = ui::Transform::ROT_180; break; case DisplayState::eOrientation270: - flags = Transform::ROT_270; + flags = ui::Transform::ROT_270; break; default: return BAD_VALUE; @@ -563,7 +563,7 @@ void DisplayDevice::setProjection(int orientation, const int w = mDisplayWidth; const int h = mDisplayHeight; - Transform R; + ui::Transform R; DisplayDevice::orientationToTransfrom(orientation, w, h, &R); if (!frame.isValid()) { @@ -578,7 +578,7 @@ void DisplayDevice::setProjection(int orientation, // it's also invalid to have an empty viewport, so we handle that // case in the same way. viewport = Rect(w, h); - if (R.getOrientation() & Transform::ROT_90) { + if (R.getOrientation() & ui::Transform::ROT_90) { // viewport is always specified in the logical orientation // of the display (ie: post-rotation). std::swap(viewport.right, viewport.bottom); @@ -587,7 +587,7 @@ void DisplayDevice::setProjection(int orientation, dirtyRegion.set(getBounds()); - Transform TL, TP, S; + ui::Transform TL, TP, S; float src_width = viewport.width(); float src_height = viewport.height(); float dst_width = frame.width(); @@ -621,7 +621,7 @@ void DisplayDevice::setProjection(int orientation, const uint8_t type = mGlobalTransform.getType(); mNeedsFiltering = (!mGlobalTransform.preserveRects() || - (type >= Transform::SCALE)); + (type >= ui::Transform::SCALE)); mScissor = mGlobalTransform.transform(viewport); if (mScissor.isEmpty()) { @@ -633,16 +633,16 @@ void DisplayDevice::setProjection(int orientation, uint32_t transform = 0; switch (mOrientation) { case DisplayState::eOrientationDefault: - transform = Transform::ROT_0; + transform = ui::Transform::ROT_0; break; case DisplayState::eOrientation90: - transform = Transform::ROT_90; + transform = ui::Transform::ROT_90; break; case DisplayState::eOrientation180: - transform = Transform::ROT_180; + transform = ui::Transform::ROT_180; break; case DisplayState::eOrientation270: - transform = Transform::ROT_270; + transform = ui::Transform::ROT_270; break; } sPrimaryDisplayOrientation = transform; @@ -656,7 +656,7 @@ uint32_t DisplayDevice::getPrimaryDisplayOrientationTransform() { } void DisplayDevice::dump(String8& result) const { - const Transform& tr(mGlobalTransform); + const ui::Transform& tr(mGlobalTransform); ANativeWindow* const window = mNativeWindow.get(); result.appendFormat("+ DisplayDevice: %s\n", mDisplayName.c_str()); result.appendFormat(" type=%x, ID=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p " diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index f440d29ad7..bcb2976998 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -17,19 +17,20 @@ #ifndef ANDROID_DISPLAY_DEVICE_H #define ANDROID_DISPLAY_DEVICE_H -#include "Transform.h" - #include -#include -#include +#include +#include +#include #include -#include #include +#include +#include #include #include #include +#include #include #include #include @@ -38,9 +39,6 @@ #include "RenderArea.h" #include "RenderEngine/Surface.h" -#include -#include - struct ANativeWindow; namespace android { @@ -126,7 +124,7 @@ public: int getOrientation() const { return mOrientation; } uint32_t getOrientationTransform() const; static uint32_t getPrimaryDisplayOrientationTransform(); - const Transform& getTransform() const { return mGlobalTransform; } + const ui::Transform& getTransform() const { return mGlobalTransform; } const Rect getViewport() const { return mViewport; } const Rect getFrame() const { return mFrame; } const Rect& getScissor() const { return mScissor; } @@ -254,7 +252,7 @@ private: * Transaction state */ static status_t orientationToTransfrom(int orientation, - int w, int h, Transform* tr); + int w, int h, ui::Transform* tr); // The identifier of the active layer stack for this display. Several displays // can use the same layer stack: A z-ordered group of layers (sometimes called @@ -269,7 +267,7 @@ private: Rect mFrame; // pre-computed scissor to apply to the display Rect mScissor; - Transform mGlobalTransform; + ui::Transform mGlobalTransform; bool mNeedsFiltering; // Current power mode int mPowerMode; @@ -344,7 +342,7 @@ public: : RenderArea(reqHeight, reqWidth, CaptureFill::OPAQUE, rotation), mDevice(device), mSourceCrop(sourceCrop) {} - const Transform& getTransform() const override { return mDevice->getTransform(); } + const ui::Transform& getTransform() const override { return mDevice->getTransform(); } Rect getBounds() const override { return mDevice->getBounds(); } int getHeight() const override { return mDevice->getHeight(); } int getWidth() const override { return mDevice->getWidth(); } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 35cbda061d..f7f3fac934 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -295,7 +295,7 @@ Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { win.intersect(crop, &win); } - Transform t = getTransform(); + ui::Transform t = getTransform(); win = t.transform(win); Rect finalCrop = getFinalCrop(s); @@ -349,7 +349,7 @@ FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const { parentBounds = p->computeBounds(Region()); } - Transform t = s.active_legacy.transform; + ui::Transform t = s.active_legacy.transform; if (p != nullptr || !s.finalCrop_legacy.isEmpty()) { floatWin = t.transform(floatWin); @@ -383,7 +383,7 @@ Rect Layer::computeInitialCrop(const sp& display) const { activeCrop.intersect(crop, &activeCrop); } - Transform t = getTransform(); + ui::Transform t = getTransform(); activeCrop = t.transform(activeCrop); if (!activeCrop.intersect(display->getViewport(), &activeCrop)) { activeCrop.clear(); @@ -414,7 +414,7 @@ FloatRect Layer::computeCrop(const sp& display) const { // Screen space to make reduction to parent crop clearer. Rect activeCrop = computeInitialCrop(display); - Transform t = getTransform(); + ui::Transform t = getTransform(); // Back to layer space to work with the content crop. activeCrop = t.inverse().transform(activeCrop); @@ -446,7 +446,8 @@ FloatRect Layer::computeCrop(const sp& display) const { invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H; } // and apply to the current transform - invTransform = (Transform(invTransformOrient) * Transform(invTransform)).getOrientation(); + invTransform = (ui::Transform(invTransformOrient) * + ui::Transform(invTransform)).getOrientation(); } int winWidth = getActiveWidth(s); @@ -519,7 +520,7 @@ void Layer::setGeometry(const sp& display, uint32_t z) { // apply the layer's transform, followed by the display's global transform // here we're guaranteed that the layer's transform preserves rects Region activeTransparentRegion(getActiveTransparentRegion(s)); - Transform t = getTransform(); + ui::Transform t = getTransform(); Rect activeCrop = getCrop(s); if (!activeCrop.isEmpty()) { activeCrop = t.transform(activeCrop); @@ -557,7 +558,7 @@ void Layer::setGeometry(const sp& display, uint32_t z) { if (!frame.intersect(display->getViewport(), &frame)) { frame.clear(); } - const Transform& tr = display->getTransform(); + const ui::Transform& tr = display->getTransform(); Rect transformedFrame = tr.transform(frame); error = hwcLayer->setDisplayFrame(transformedFrame); if (error != HWC2::Error::None) { @@ -613,8 +614,8 @@ void Layer::setGeometry(const sp& display, uint32_t z) { * (NOTE: the matrices are multiplied in reverse order) */ - const Transform bufferOrientation(mCurrentTransform); - Transform transform(tr * t * bufferOrientation); + const ui::Transform bufferOrientation(mCurrentTransform); + ui::Transform transform(tr * t * bufferOrientation); if (getTransformToDisplayInverse()) { /* @@ -633,12 +634,12 @@ void Layer::setGeometry(const sp& display, uint32_t z) { * computation so it's enough to just omit it in the composition. * See comment in onDraw with ref to b/36727915 for why. */ - transform = Transform(invTransform) * tr * bufferOrientation; + transform = ui::Transform(invTransform) * tr * bufferOrientation; } // this gives us only the "orientation" component of the transform const uint32_t orientation = transform.getOrientation(); - if (orientation & Transform::ROT_INVALID) { + if (orientation & ui::Transform::ROT_INVALID) { // we can only handle simple transformation hwcInfo.forceClientComposition = true; } else { @@ -831,7 +832,7 @@ static void boundPoint(vec2* point, const Rect& crop) { void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh, bool useIdentityTransform) const { const Layer::State& s(getDrawingState()); - const Transform renderAreaTransform(renderArea.getTransform()); + const ui::Transform renderAreaTransform(renderArea.getTransform()); const uint32_t height = renderArea.getHeight(); FloatRect win = computeBounds(); @@ -840,7 +841,7 @@ void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh, vec2 rb = vec2(win.right, win.bottom); vec2 rt = vec2(win.right, win.top); - Transform layerTransform = getTransform(); + ui::Transform layerTransform = getTransform(); if (!useIdentityTransform) { lt = layerTransform.transform(lt); lb = layerTransform.transform(lb); @@ -1104,7 +1105,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { // we may use linear filtering, if the matrix scales us const uint8_t type = getActiveTransform(c).getType(); - mNeedsFiltering = (!getActiveTransform(c).preserveRects() || (type >= Transform::SCALE)); + mNeedsFiltering = (!getActiveTransform(c).preserveRects() || type >= ui::Transform::SCALE); } // If the layer is hidden, signal and clear out all local sync points so @@ -1279,7 +1280,7 @@ bool Layer::setColor(const half3& color) { bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix, bool allowNonRectPreservingTransforms) { - Transform t; + ui::Transform t; t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); if (!allowNonRectPreservingTransforms && !t.preserveRects()) { @@ -1418,9 +1419,9 @@ void Layer::updateTransformHint(const sp& display) const { // The transform hint is used to improve performance, but we can // only have a single transform hint, it cannot // apply to all displays. - const Transform& planeTransform = display->getTransform(); + const ui::Transform& planeTransform = display->getTransform(); orientation = planeTransform.getOrientation(); - if (orientation & Transform::ROT_INVALID) { + if (orientation & ui::Transform::ROT_INVALID) { orientation = 0; } } @@ -1885,8 +1886,8 @@ void Layer::traverseChildrenInZOrder(LayerVector::StateSet stateSet, traverseChildrenInZOrderInner(layersInTree, stateSet, visitor); } -Transform Layer::getTransform() const { - Transform t; +ui::Transform Layer::getTransform() const { + ui::Transform t; const auto& p = mDrawingParent.promote(); if (p != nullptr) { t = p->getTransform(); @@ -1908,7 +1909,7 @@ Transform Layer::getTransform() const { } float sx = p->getActiveWidth(p->getDrawingState()) / static_cast(bufferWidth); float sy = p->getActiveHeight(p->getDrawingState()) / static_cast(bufferHeight); - Transform extraParentScaling; + ui::Transform extraParentScaling; extraParentScaling.set(sx, 0, 0, sy); t = t * extraParentScaling; } @@ -1942,8 +1943,8 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; const State& state = useDrawing ? mDrawingState : mCurrentState; - Transform requestedTransform = state.active_legacy.transform; - Transform transform = getTransform(); + ui::Transform requestedTransform = state.active_legacy.transform; + ui::Transform transform = getTransform(); layerInfo->set_id(sequence); layerInfo->set_name(getName().c_str()); @@ -2011,7 +2012,7 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) auto buffer = getBE().compositionInfo.mBuffer; if (buffer != nullptr) { LayerProtoHelper::writeToProto(buffer, layerInfo->mutable_active_buffer()); - LayerProtoHelper::writeToProto(Transform(mCurrentTransform), + LayerProtoHelper::writeToProto(ui::Transform(mCurrentTransform), layerInfo->mutable_buffer_transform()); } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 814adf78bb..6ebd668959 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -28,10 +28,11 @@ #include #include #include +#include +#include #include #include -#include #include #include @@ -43,7 +44,6 @@ #include "MonitoredProducer.h" #include "SurfaceFlinger.h" #include "TimeStats/TimeStats.h" -#include "Transform.h" #include #include "DisplayHardware/HWComposer.h" @@ -101,7 +101,7 @@ public: struct Geometry { uint32_t w; uint32_t h; - Transform transform; + ui::Transform transform; inline bool operator==(const Geometry& rhs) const { return (w == rhs.w && h == rhs.h) && (transform.tx() == rhs.transform.tx()) && @@ -345,7 +345,7 @@ public: virtual Geometry getActiveGeometry(const Layer::State& s) const { return s.active_legacy; } virtual uint32_t getActiveWidth(const Layer::State& s) const { return s.active_legacy.w; } virtual uint32_t getActiveHeight(const Layer::State& s) const { return s.active_legacy.h; } - virtual Transform getActiveTransform(const Layer::State& s) const { + virtual ui::Transform getActiveTransform(const Layer::State& s) const { return s.active_legacy.transform; } virtual Region getActiveTransparentRegion(const Layer::State& s) const { @@ -545,7 +545,7 @@ public: virtual bool getTransformToDisplayInverse() const { return false; } - Transform getTransform() const; + ui::Transform getTransform() const; // Returns the Alpha of the Surface, accounting for the Alpha // of parent Surfaces in the hierarchy (alpha's will be multiplied diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index cc3955087a..3289e8f583 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -51,7 +51,8 @@ void LayerProtoHelper::writeToProto(const half4 color, ColorProto* colorProto) { colorProto->set_a(color.a); } -void LayerProtoHelper::writeToProto(const Transform& transform, TransformProto* transformProto) { +void LayerProtoHelper::writeToProto(const ui::Transform& transform, + TransformProto* transformProto) { transformProto->set_dsdx(transform[0][0]); transformProto->set_dtdx(transform[0][1]); transformProto->set_dsdy(transform[1][0]); diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h index 860da63ed2..6df5aeaebf 100644 --- a/services/surfaceflinger/LayerProtoHelper.h +++ b/services/surfaceflinger/LayerProtoHelper.h @@ -16,13 +16,11 @@ #include +#include #include #include #include - -#include - -#include +#include namespace android { namespace surfaceflinger { @@ -32,7 +30,7 @@ public: static void writeToProto(const FloatRect& rect, FloatRectProto* rectProto); static void writeToProto(const Region& region, RegionProto* regionProto); static void writeToProto(const half4 color, ColorProto* colorProto); - static void writeToProto(const Transform& transform, TransformProto* transformProto); + static void writeToProto(const ui::Transform& transform, TransformProto* transformProto); static void writeToProto(const sp& buffer, ActiveBufferProto* activeBufferProto); }; diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp index bd59d17ac2..136cdc03f7 100644 --- a/services/surfaceflinger/LayerRejecter.cpp +++ b/services/surfaceflinger/LayerRejecter.cpp @@ -50,13 +50,13 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) // check that we received a buffer of the right size // (Take the buffer's orientation into account) - if (item.mTransform & Transform::ROT_90) { + if (item.mTransform & ui::Transform::ROT_90) { std::swap(bufWidth, bufHeight); } if (mTransformToDisplayInverse) { uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); - if (invTransform & Transform::ROT_90) { + if (invTransform & ui::Transform::ROT_90) { std::swap(bufWidth, bufHeight); } } diff --git a/services/surfaceflinger/RenderArea.cpp b/services/surfaceflinger/RenderArea.cpp index 1a8edf3e79..7f69ce4b3e 100644 --- a/services/surfaceflinger/RenderArea.cpp +++ b/services/surfaceflinger/RenderArea.cpp @@ -4,6 +4,27 @@ namespace android { +ui::Transform::orientation_flags fromRotation(ISurfaceComposer::Rotation rotation) { + switch (rotation) { + case ISurfaceComposer::eRotateNone: + return ui::Transform::ROT_0; + case ISurfaceComposer::eRotate90: + return ui::Transform::ROT_90; + case ISurfaceComposer::eRotate180: + return ui::Transform::ROT_180; + case ISurfaceComposer::eRotate270: + return ui::Transform::ROT_270; + } + ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation); + return ui::Transform::ROT_0; +} + +RenderArea::RenderArea(uint32_t reqHeight, uint32_t reqWidth, CaptureFill captureFill, + ISurfaceComposer::Rotation rotation) + : mReqHeight(reqHeight), mReqWidth(reqWidth), mCaptureFill(captureFill) { + mRotationFlags = fromRotation(rotation); +} + float RenderArea::getCaptureFillValue(CaptureFill captureFill) { switch(captureFill) { case CaptureFill::CLEAR: @@ -23,7 +44,7 @@ status_t RenderArea::updateDimensions(int displayRotation) { uint32_t width = getWidth(); uint32_t height = getHeight(); - if (mRotationFlags & Transform::ROT_90) { + if (mRotationFlags & ui::Transform::ROT_90) { std::swap(width, height); } diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index 96e4b5f48b..e38f4621d7 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -1,8 +1,8 @@ #pragma once +#include #include - -#include "Transform.h" +#include #include @@ -16,14 +16,11 @@ public: static float getCaptureFillValue(CaptureFill captureFill); RenderArea(uint32_t reqHeight, uint32_t reqWidth, CaptureFill captureFill, - ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone) - : mReqHeight(reqHeight), mReqWidth(reqWidth), mCaptureFill(captureFill) { - mRotationFlags = Transform::fromRotation(rotation); - } + ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone); virtual ~RenderArea() = default; - virtual const Transform& getTransform() const = 0; + virtual const ui::Transform& getTransform() const = 0; virtual Rect getBounds() const = 0; virtual int getHeight() const = 0; virtual int getWidth() const = 0; @@ -35,7 +32,7 @@ public: int getReqHeight() const { return mReqHeight; }; int getReqWidth() const { return mReqWidth; }; - Transform::orientation_flags getRotationFlags() const { return mRotationFlags; }; + ui::Transform::orientation_flags getRotationFlags() const { return mRotationFlags; }; status_t updateDimensions(int displayRotation); CaptureFill getCaptureFill() const { return mCaptureFill; }; @@ -43,7 +40,7 @@ public: private: uint32_t mReqHeight; uint32_t mReqWidth; - Transform::orientation_flags mRotationFlags; + ui::Transform::orientation_flags mRotationFlags; CaptureFill mCaptureFill; }; diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp index c218e4da50..d4a2bb4356 100644 --- a/services/surfaceflinger/RenderEngine/Description.cpp +++ b/services/surfaceflinger/RenderEngine/Description.cpp @@ -19,9 +19,6 @@ #include -#include -#include - #include "Description.h" namespace android { diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index 4860f3c0da..21865941ad 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -167,7 +167,7 @@ size_t GLES20RenderEngine::getMaxViewportDims() const { void GLES20RenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, bool yswap, - Transform::orientation_flags rotation) { + ui::Transform::orientation_flags rotation) { int32_t l = sourceCrop.left; int32_t r = sourceCrop.right; @@ -185,15 +185,15 @@ void GLES20RenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect s // Apply custom rotation to the projection. float rot90InRadians = 2.0f * static_cast(M_PI) / 4.0f; switch (rotation) { - case Transform::ROT_0: + case ui::Transform::ROT_0: break; - case Transform::ROT_90: + case ui::Transform::ROT_90: m = mat4::rotate(rot90InRadians, vec3(0, 0, 1)) * m; break; - case Transform::ROT_180: + case ui::Transform::ROT_180: m = mat4::rotate(rot90InRadians * 2.0f, vec3(0, 0, 1)) * m; break; - case Transform::ROT_270: + case ui::Transform::ROT_270: m = mat4::rotate(rot90InRadians * 3.0f, vec3(0, 0, 1)) * m; break; default: diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h index cc8eb1dfab..f682225730 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h @@ -21,7 +21,6 @@ #include #include -#include #include "Description.h" #include "ProgramCache.h" @@ -67,7 +66,7 @@ public: protected: virtual void dump(String8& result); virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, - bool yswap, Transform::orientation_flags rotation); + bool yswap, ui::Transform::orientation_flags rotation); virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture, const half4& color) override; diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index d2b218ee82..2ed2cc7611 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -24,9 +24,10 @@ #include #include -#include #include #include +#include +#include #define EGL_NO_CONFIG ((EGLConfig)0) @@ -105,7 +106,7 @@ public: // set-up virtual void checkErrors() const; virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, - bool yswap, Transform::orientation_flags rotation) = 0; + bool yswap, ui::Transform::orientation_flags rotation) = 0; virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture, const half4& color) = 0; virtual void setupLayerTexturing(const Texture& texture) = 0; diff --git a/services/surfaceflinger/RenderEngine/Surface.cpp b/services/surfaceflinger/RenderEngine/Surface.cpp index 0d20f1fd87..3bf42fb8f8 100644 --- a/services/surfaceflinger/RenderEngine/Surface.cpp +++ b/services/surfaceflinger/RenderEngine/Surface.cpp @@ -19,6 +19,7 @@ #include "RenderEngine.h" #include +#include namespace android { namespace RE { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 0e88fa0a72..69dfc92f88 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1821,7 +1821,7 @@ void SurfaceFlinger::rebuildLayerStacks() { Region dirtyRegion; Vector> layersSortedByZ; Vector> layersNeedingFences; - const Transform& tr = display->getTransform(); + const ui::Transform& tr = display->getTransform(); const Rect bounds = display->getBounds(); if (display->isPoweredOn()) { computeVisibleRegions(display, dirtyRegion, opaqueRegion); @@ -2639,7 +2639,7 @@ void SurfaceFlinger::computeVisibleRegions(const sp& displa const bool translucent = !layer->isOpaque(s); Rect bounds(layer->computeScreenBounds()); visibleRegion.set(bounds); - Transform tr = layer->getTransform(); + ui::Transform tr = layer->getTransform(); if (!visibleRegion.isEmpty()) { // Remove the transparent area from the visible region if (translucent) { @@ -2656,7 +2656,7 @@ void SurfaceFlinger::computeVisibleRegions(const sp& displa // compute the opaque region const int32_t layerOrientation = tr.getOrientation(); if (layer->getAlpha() == 1.0f && !translucent && - ((layerOrientation & Transform::ROT_INVALID) == false)) { + ((layerOrientation & ui::Transform::ROT_INVALID) == false)) { // the opaque region is the layer's footprint opaqueRegion = visibleRegion; } @@ -2919,7 +2919,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& display) { */ ALOGV("Rendering client layers"); - const Transform& displayTransform = display->getTransform(); + const ui::Transform& displayTransform = display->getTransform(); bool firstLayer = true; for (auto& layer : display->getVisibleLayersSortedByZ()) { const Region clip(bounds.intersect( @@ -4845,7 +4845,7 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, mCrop(crop), mFlinger(flinger), mChildrenOnly(childrenOnly) {} - const Transform& getTransform() const override { return mTransform; } + const ui::Transform& getTransform() const override { return mTransform; } Rect getBounds() const override { const Layer::State& layerState(mLayer->getDrawingState()); return Rect(mLayer->getActiveWidth(layerState), mLayer->getActiveHeight(layerState)); @@ -4897,7 +4897,7 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, // In the "childrenOnly" case we reparent the children to a screenshot // layer which has no properties set and which does not draw. sp screenshotParentLayer; - Transform mTransform; + ui::Transform mTransform; SurfaceFlinger* mFlinger; const bool mChildrenOnly; @@ -5051,17 +5051,17 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, sourceCrop.setLeftTop(Point(0, 0)); sourceCrop.setRightBottom(Point(raWidth, raHeight)); } else if (mPrimaryDisplayOrientation != DisplayState::eOrientationDefault) { - Transform tr; + ui::Transform tr; uint32_t flags = 0x00; switch (mPrimaryDisplayOrientation) { case DisplayState::eOrientation90: - flags = Transform::ROT_90; + flags = ui::Transform::ROT_90; break; case DisplayState::eOrientation180: - flags = Transform::ROT_180; + flags = ui::Transform::ROT_180; break; case DisplayState::eOrientation270: - flags = Transform::ROT_270; + flags = ui::Transform::ROT_270; break; } tr.set(flags, raWidth, raHeight); @@ -5089,7 +5089,7 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, // make sure to clear all GL error flags engine.checkErrors(); - Transform::orientation_flags rotation = renderArea.getRotationFlags(); + ui::Transform::orientation_flags rotation = renderArea.getRotationFlags(); if (mPrimaryDisplayOrientation != DisplayState::eOrientationDefault) { // convert hw orientation into flag presentation // here inverse transform needed @@ -5097,26 +5097,26 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, uint8_t hw_flip_hv = 0x00; switch (mPrimaryDisplayOrientation) { case DisplayState::eOrientation90: - hw_rot_90 = Transform::ROT_90; - hw_flip_hv = Transform::ROT_180; + hw_rot_90 = ui::Transform::ROT_90; + hw_flip_hv = ui::Transform::ROT_180; break; case DisplayState::eOrientation180: - hw_flip_hv = Transform::ROT_180; + hw_flip_hv = ui::Transform::ROT_180; break; case DisplayState::eOrientation270: - hw_rot_90 = Transform::ROT_90; + hw_rot_90 = ui::Transform::ROT_90; break; } // transform flags operation // 1) flip H V if both have ROT_90 flag // 2) XOR these flags - uint8_t rotation_rot_90 = rotation & Transform::ROT_90; - uint8_t rotation_flip_hv = rotation & Transform::ROT_180; + uint8_t rotation_rot_90 = rotation & ui::Transform::ROT_90; + uint8_t rotation_flip_hv = rotation & ui::Transform::ROT_180; if (rotation_rot_90 & hw_rot_90) { - rotation_flip_hv = (~rotation_flip_hv) & Transform::ROT_180; + rotation_flip_hv = (~rotation_flip_hv) & ui::Transform::ROT_180; } - rotation = static_cast + rotation = static_cast ((rotation_rot_90 ^ hw_rot_90) | (rotation_flip_hv ^ hw_flip_hv)); } diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp deleted file mode 100644 index bc9e5cd5d7..0000000000 --- a/services/surfaceflinger/Transform.cpp +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#include - -#include -#include -#include - -#include "Transform.h" - -// --------------------------------------------------------------------------- - -namespace android { - -// --------------------------------------------------------------------------- - -Transform::Transform() { - reset(); -} - -Transform::Transform(const Transform& other) - : mMatrix(other.mMatrix), mType(other.mType) { -} - -Transform::Transform(uint32_t orientation) { - set(orientation, 0, 0); -} - -Transform::~Transform() { -} - -static const float EPSILON = 0.0f; - -bool Transform::isZero(float f) { - return fabs(f) <= EPSILON; -} - -bool Transform::absIsOne(float f) { - return isZero(fabs(f) - 1.0f); -} - -Transform Transform::operator * (const Transform& rhs) const -{ - if (CC_LIKELY(mType == IDENTITY)) - return rhs; - - Transform r(*this); - if (rhs.mType == IDENTITY) - return r; - - // TODO: we could use mType to optimize the matrix multiply - const mat33& A(mMatrix); - const mat33& B(rhs.mMatrix); - mat33& D(r.mMatrix); - for (int i=0 ; i<3 ; i++) { - const float v0 = A[0][i]; - const float v1 = A[1][i]; - const float v2 = A[2][i]; - D[0][i] = v0*B[0][0] + v1*B[0][1] + v2*B[0][2]; - D[1][i] = v0*B[1][0] + v1*B[1][1] + v2*B[1][2]; - D[2][i] = v0*B[2][0] + v1*B[2][1] + v2*B[2][2]; - } - r.mType |= rhs.mType; - - // TODO: we could recompute this value from r and rhs - r.mType &= 0xFF; - r.mType |= UNKNOWN_TYPE; - return r; -} - -const vec3& Transform::operator [] (size_t i) const { - return mMatrix[i]; -} - -float Transform::tx() const { - return mMatrix[2][0]; -} - -float Transform::ty() const { - return mMatrix[2][1]; -} - -void Transform::reset() { - mType = IDENTITY; - for(int i=0 ; i<3 ; i++) { - vec3& v(mMatrix[i]); - for (int j=0 ; j<3 ; j++) - v[j] = ((i==j) ? 1.0f : 0.0f); - } -} - -void Transform::set(float tx, float ty) -{ - mMatrix[2][0] = tx; - mMatrix[2][1] = ty; - mMatrix[2][2] = 1.0f; - - if (isZero(tx) && isZero(ty)) { - mType &= ~TRANSLATE; - } else { - mType |= TRANSLATE; - } -} - -void Transform::set(float a, float b, float c, float d) -{ - mat33& M(mMatrix); - M[0][0] = a; M[1][0] = b; - M[0][1] = c; M[1][1] = d; - M[0][2] = 0; M[1][2] = 0; - mType = UNKNOWN_TYPE; -} - -status_t Transform::set(uint32_t flags, float w, float h) -{ - if (flags & ROT_INVALID) { - // that's not allowed! - reset(); - return BAD_VALUE; - } - - Transform H, V, R; - if (flags & ROT_90) { - // w & h are inverted when rotating by 90 degrees - std::swap(w, h); - } - - if (flags & FLIP_H) { - H.mType = (FLIP_H << 8) | SCALE; - H.mType |= isZero(w) ? IDENTITY : TRANSLATE; - mat33& M(H.mMatrix); - M[0][0] = -1; - M[2][0] = w; - } - - if (flags & FLIP_V) { - V.mType = (FLIP_V << 8) | SCALE; - V.mType |= isZero(h) ? IDENTITY : TRANSLATE; - mat33& M(V.mMatrix); - M[1][1] = -1; - M[2][1] = h; - } - - if (flags & ROT_90) { - const float original_w = h; - R.mType = (ROT_90 << 8) | ROTATE; - R.mType |= isZero(original_w) ? IDENTITY : TRANSLATE; - mat33& M(R.mMatrix); - M[0][0] = 0; M[1][0] =-1; M[2][0] = original_w; - M[0][1] = 1; M[1][1] = 0; - } - - *this = (R*(H*V)); - return NO_ERROR; -} - -vec2 Transform::transform(const vec2& v) const { - vec2 r; - const mat33& M(mMatrix); - r[0] = M[0][0]*v[0] + M[1][0]*v[1] + M[2][0]; - r[1] = M[0][1]*v[0] + M[1][1]*v[1] + M[2][1]; - return r; -} - -vec3 Transform::transform(const vec3& v) const { - vec3 r; - const mat33& M(mMatrix); - r[0] = M[0][0]*v[0] + M[1][0]*v[1] + M[2][0]*v[2]; - r[1] = M[0][1]*v[0] + M[1][1]*v[1] + M[2][1]*v[2]; - r[2] = M[0][2]*v[0] + M[1][2]*v[1] + M[2][2]*v[2]; - return r; -} - -vec2 Transform::transform(int x, int y) const -{ - return transform(vec2(x,y)); -} - -Rect Transform::makeBounds(int w, int h) const -{ - return transform( Rect(w, h) ); -} - -Rect Transform::transform(const Rect& bounds, bool roundOutwards) const -{ - Rect r; - vec2 lt( bounds.left, bounds.top ); - vec2 rt( bounds.right, bounds.top ); - vec2 lb( bounds.left, bounds.bottom ); - vec2 rb( bounds.right, bounds.bottom ); - - lt = transform(lt); - rt = transform(rt); - lb = transform(lb); - rb = transform(rb); - - if (roundOutwards) { - r.left = floorf(std::min({lt[0], rt[0], lb[0], rb[0]})); - r.top = floorf(std::min({lt[1], rt[1], lb[1], rb[1]})); - r.right = ceilf(std::max({lt[0], rt[0], lb[0], rb[0]})); - r.bottom = ceilf(std::max({lt[1], rt[1], lb[1], rb[1]})); - } else { - r.left = floorf(std::min({lt[0], rt[0], lb[0], rb[0]}) + 0.5f); - r.top = floorf(std::min({lt[1], rt[1], lb[1], rb[1]}) + 0.5f); - r.right = floorf(std::max({lt[0], rt[0], lb[0], rb[0]}) + 0.5f); - r.bottom = floorf(std::max({lt[1], rt[1], lb[1], rb[1]}) + 0.5f); - } - - return r; -} - -FloatRect Transform::transform(const FloatRect& bounds) const -{ - vec2 lt(bounds.left, bounds.top); - vec2 rt(bounds.right, bounds.top); - vec2 lb(bounds.left, bounds.bottom); - vec2 rb(bounds.right, bounds.bottom); - - lt = transform(lt); - rt = transform(rt); - lb = transform(lb); - rb = transform(rb); - - FloatRect r; - r.left = std::min({lt[0], rt[0], lb[0], rb[0]}); - r.top = std::min({lt[1], rt[1], lb[1], rb[1]}); - r.right = std::max({lt[0], rt[0], lb[0], rb[0]}); - r.bottom = std::max({lt[1], rt[1], lb[1], rb[1]}); - - return r; -} - -Region Transform::transform(const Region& reg) const -{ - Region out; - if (CC_UNLIKELY(type() > TRANSLATE)) { - if (CC_LIKELY(preserveRects())) { - Region::const_iterator it = reg.begin(); - Region::const_iterator const end = reg.end(); - while (it != end) { - out.orSelf(transform(*it++)); - } - } else { - out.set(transform(reg.bounds())); - } - } else { - int xpos = floorf(tx() + 0.5f); - int ypos = floorf(ty() + 0.5f); - out = reg.translate(xpos, ypos); - } - return out; -} - -uint32_t Transform::type() const -{ - if (mType & UNKNOWN_TYPE) { - // recompute what this transform is - - const mat33& M(mMatrix); - const float a = M[0][0]; - const float b = M[1][0]; - const float c = M[0][1]; - const float d = M[1][1]; - const float x = M[2][0]; - const float y = M[2][1]; - - bool scale = false; - uint32_t flags = ROT_0; - if (isZero(b) && isZero(c)) { - if (a<0) flags |= FLIP_H; - if (d<0) flags |= FLIP_V; - if (!absIsOne(a) || !absIsOne(d)) { - scale = true; - } - } else if (isZero(a) && isZero(d)) { - flags |= ROT_90; - if (b>0) flags |= FLIP_V; - if (c<0) flags |= FLIP_H; - if (!absIsOne(b) || !absIsOne(c)) { - scale = true; - } - } else { - // there is a skew component and/or a non 90 degrees rotation - flags = ROT_INVALID; - } - - mType = flags << 8; - if (flags & ROT_INVALID) { - mType |= UNKNOWN; - } else { - if ((flags & ROT_90) || ((flags & ROT_180) == ROT_180)) - mType |= ROTATE; - if (flags & FLIP_H) - mType ^= SCALE; - if (flags & FLIP_V) - mType ^= SCALE; - if (scale) - mType |= SCALE; - } - - if (!isZero(x) || !isZero(y)) - mType |= TRANSLATE; - } - return mType; -} - -Transform Transform::inverse() const { - // our 3x3 matrix is always of the form of a 2x2 transformation - // followed by a translation: T*M, therefore: - // (T*M)^-1 = M^-1 * T^-1 - Transform result; - if (mType <= TRANSLATE) { - // 1 0 0 - // 0 1 0 - // x y 1 - result = *this; - result.mMatrix[2][0] = -result.mMatrix[2][0]; - result.mMatrix[2][1] = -result.mMatrix[2][1]; - } else { - // a c 0 - // b d 0 - // x y 1 - const mat33& M(mMatrix); - const float a = M[0][0]; - const float b = M[1][0]; - const float c = M[0][1]; - const float d = M[1][1]; - const float x = M[2][0]; - const float y = M[2][1]; - - const float idet = 1.0 / (a*d - b*c); - result.mMatrix[0][0] = d*idet; - result.mMatrix[0][1] = -c*idet; - result.mMatrix[1][0] = -b*idet; - result.mMatrix[1][1] = a*idet; - result.mType = mType; - - vec2 T(-x, -y); - T = result.transform(T); - result.mMatrix[2][0] = T[0]; - result.mMatrix[2][1] = T[1]; - } - return result; -} - -uint32_t Transform::getType() const { - return type() & 0xFF; -} - -uint32_t Transform::getOrientation() const -{ - return (type() >> 8) & 0xFF; -} - -bool Transform::preserveRects() const -{ - return (getOrientation() & ROT_INVALID) ? false : true; -} - -void Transform::dump(const char* name) const -{ - type(); // updates the type - - String8 flags, type; - const mat33& m(mMatrix); - uint32_t orient = mType >> 8; - - if (orient&ROT_INVALID) { - flags.append("ROT_INVALID "); - } else { - if (orient&ROT_90) { - flags.append("ROT_90 "); - } else { - flags.append("ROT_0 "); - } - if (orient&FLIP_V) - flags.append("FLIP_V "); - if (orient&FLIP_H) - flags.append("FLIP_H "); - } - - if (!(mType&(SCALE|ROTATE|TRANSLATE))) - type.append("IDENTITY "); - if (mType&SCALE) - type.append("SCALE "); - if (mType&ROTATE) - type.append("ROTATE "); - if (mType&TRANSLATE) - type.append("TRANSLATE "); - - ALOGD("%s 0x%08x (%s, %s)", name, mType, flags.string(), type.string()); - ALOGD("%.4f %.4f %.4f", m[0][0], m[1][0], m[2][0]); - ALOGD("%.4f %.4f %.4f", m[0][1], m[1][1], m[2][1]); - ALOGD("%.4f %.4f %.4f", m[0][2], m[1][2], m[2][2]); -} - -Transform::orientation_flags Transform::fromRotation(ISurfaceComposer::Rotation rotation) { - // Convert to surfaceflinger's internal rotation type. - switch (rotation) { - case ISurfaceComposer::eRotateNone: - return Transform::ROT_0; - case ISurfaceComposer::eRotate90: - return Transform::ROT_90; - case ISurfaceComposer::eRotate180: - return Transform::ROT_180; - case ISurfaceComposer::eRotate270: - return Transform::ROT_270; - default: - ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation); - return Transform::ROT_0; - } -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/services/surfaceflinger/Transform.h b/services/surfaceflinger/Transform.h deleted file mode 100644 index b11d0576c4..0000000000 --- a/services/surfaceflinger/Transform.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#ifndef ANDROID_TRANSFORM_H -#define ANDROID_TRANSFORM_H - -#include -#include - -#include -#include -#include -#include - -#include - -#include - -namespace android { - -class Region; - -// --------------------------------------------------------------------------- - -class Transform -{ -public: - Transform(); - Transform(const Transform& other); - explicit Transform(uint32_t orientation); - ~Transform(); - - enum orientation_flags { - ROT_0 = 0x00000000, - FLIP_H = HAL_TRANSFORM_FLIP_H, - FLIP_V = HAL_TRANSFORM_FLIP_V, - ROT_90 = HAL_TRANSFORM_ROT_90, - ROT_180 = FLIP_H|FLIP_V, - ROT_270 = ROT_180|ROT_90, - ROT_INVALID = 0x80 - }; - - static orientation_flags fromRotation(ISurfaceComposer::Rotation rotation); - - enum type_mask { - IDENTITY = 0, - TRANSLATE = 0x1, - ROTATE = 0x2, - SCALE = 0x4, - UNKNOWN = 0x8 - }; - - // query the transform - bool preserveRects() const; - uint32_t getType() const; - uint32_t getOrientation() const; - - const vec3& operator [] (size_t i) const; // returns column i - float tx() const; - float ty() const; - - // modify the transform - void reset(); - void set(float tx, float ty); - void set(float a, float b, float c, float d); - status_t set(uint32_t flags, float w, float h); - - // transform data - Rect makeBounds(int w, int h) const; - vec2 transform(int x, int y) const; - Region transform(const Region& reg) const; - Rect transform(const Rect& bounds, - bool roundOutwards = false) const; - FloatRect transform(const FloatRect& bounds) const; - Transform operator * (const Transform& rhs) const; - // assumes the last row is < 0 , 0 , 1 > - vec2 transform(const vec2& v) const; - vec3 transform(const vec3& v) const; - - Transform inverse() const; - - // for debugging - void dump(const char* name) const; - -private: - struct mat33 { - vec3 v[3]; - inline const vec3& operator [] (int i) const { return v[i]; } - inline vec3& operator [] (int i) { return v[i]; } - }; - - enum { UNKNOWN_TYPE = 0x80000000 }; - - uint32_t type() const; - static bool absIsOne(float f); - static bool isZero(float f); - - mat33 mMatrix; - mutable uint32_t mType; -}; - -// --------------------------------------------------------------------------- -}; // namespace android - -#endif /* ANDROID_TRANSFORM_H */ diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h index 7814d32b19..36f74b6c51 100644 --- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h +++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h @@ -56,7 +56,7 @@ public: MOCK_METHOD5(readPixels, void(size_t, size_t, size_t, size_t, uint32_t*)); MOCK_CONST_METHOD0(checkErrors, void()); MOCK_METHOD6(setViewportAndProjection, - void(size_t, size_t, Rect, size_t, bool, Transform::orientation_flags)); + void(size_t, size_t, Rect, size_t, bool, ui::Transform::orientation_flags)); MOCK_METHOD4(setupLayerBlending, void(bool, bool, bool, const half4&)); MOCK_METHOD1(setupLayerTexturing, void(const Texture&)); MOCK_METHOD0(setupLayerBlackedOut, void()); -- cgit v1.2.3-59-g8ed1b From d01c4437b143b5f7ee5f35344da44806d76440f9 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Mon, 13 Aug 2018 10:38:47 -0700 Subject: SF: Set the buffer size immediately when applying a transaction If deferred transactions changes the buffer size as well, then the client will not receive the correct buffer size to render its contents. Bug: 111504081, 110763772 Test: go/wm-smoke Test: mmma frameworks/native/services/surfaceflinger/tests/ && \ mmma frameworks/native/libs/gui/tests/ && adb sync data && \ adb shell /data/nativetest/libgui_test/libgui_test && \ adb shell /data/nativetest/libsurfaceflinger_unittest/libsurfaceflinger_unittest && \ adb shell /data/nativetest/SurfaceFlinger_test/SurfaceFlinger_test && \ adb shell /data/nativetest/SurfaceParcelable_test/SurfaceParcelable_test && \ adb shell /data/nativetest/sffakehwc_test/sffakehwc_test && \ adb shell /data/nativetest64/libgui_test/libgui_test && \ adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest && \ adb shell /data/nativetest64/SurfaceFlinger_test/SurfaceFlinger_test && \ adb shell /data/nativetest64/SurfaceParcelable_test/SurfaceParcelable_test && \ adb shell /data/nativetest64/sffakehwc_test/sffakehwc_test && \ echo "ALL TESTS PASSED" Change-Id: Id7c9662d9b755645b4cfadab2add285964adf4a4 --- libs/gui/SurfaceComposerClient.cpp | 3 --- services/surfaceflinger/Layer.cpp | 8 ++++---- 2 files changed, 4 insertions(+), 7 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 17cff546e0..d0ac8de7a2 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -240,9 +240,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSize( s->w = w; s->h = h; - // Resizing a surface makes the transaction synchronous. - mForceSynchronous = true; - return *this; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f7f3fac934..04beae0c55 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1013,10 +1013,6 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { s.active_legacy.w, s.active_legacy.h, s.crop_legacy.left, s.crop_legacy.top, s.crop_legacy.right, s.crop_legacy.bottom, s.crop_legacy.getWidth(), s.crop_legacy.getHeight(), s.requested_legacy.w, s.requested_legacy.h); - - // record the new size, form this point on, when the client request - // a buffer, it'll get the new size. - setDefaultBufferSize(stateToCommit->requested_legacy.w, stateToCommit->requested_legacy.h); } // Don't let Layer::doTransaction update the drawing state @@ -1253,6 +1249,10 @@ bool Layer::setSize(uint32_t w, uint32_t h) { mCurrentState.requested_legacy.h = h; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); + + // record the new size, from this point on, when the client request + // a buffer, it'll get the new size. + setDefaultBufferSize(mCurrentState.requested_legacy.w, mCurrentState.requested_legacy.h); return true; } bool Layer::setAlpha(float alpha) { -- cgit v1.2.3-59-g8ed1b From ba34049dabfa1170dd2642aeb02b7bf597f45bb7 Mon Sep 17 00:00:00 2001 From: David Sodman Date: Sun, 5 Aug 2018 21:51:33 -0700 Subject: SF: Update CompositionInfo during calculation Bug: 112259502 Test: cts -m CtsViewTestCases SurfaceFlinger_test vrflinger_test Change-Id: I9b7de78957c8c0a2202b0c8c715d6aa31960d00f --- services/surfaceflinger/BufferLayer.cpp | 6 ++++++ services/surfaceflinger/BufferQueueLayer.cpp | 3 +++ services/surfaceflinger/ColorLayer.cpp | 6 ++++++ services/surfaceflinger/Layer.cpp | 10 ++++++++++ services/surfaceflinger/Layer.h | 8 ++++++++ services/surfaceflinger/LayerBE.h | 2 ++ services/surfaceflinger/SurfaceFlinger.cpp | 16 ++++++++++++++++ services/surfaceflinger/SurfaceFlinger.h | 3 +++ 8 files changed, 54 insertions(+) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index e1094d828a..f48aa47962 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -275,6 +275,7 @@ void BufferLayer::setPerFrameData(const sp& display) { to_string(error).c_str(), static_cast(error)); visible.dump(LOG_TAG); } + getBE().compositionInfo.hwc.visibleRegion = visible; error = hwcLayer->setSurfaceDamage(surfaceDamageRegion); if (error != HWC2::Error::None) { @@ -282,6 +283,7 @@ void BufferLayer::setPerFrameData(const sp& display) { to_string(error).c_str(), static_cast(error)); surfaceDamageRegion.dump(LOG_TAG); } + getBE().compositionInfo.hwc.surfaceDamage = surfaceDamageRegion; // Sideband layers if (getBE().compositionInfo.hwc.sidebandStream.get()) { @@ -293,6 +295,7 @@ void BufferLayer::setPerFrameData(const sp& display) { getBE().compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(), static_cast(error)); } + getBE().compositionInfo.compositionType = HWC2::Composition::Sideband; return; } @@ -318,6 +321,9 @@ void BufferLayer::setPerFrameData(const sp& display) { ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), to_string(error).c_str(), static_cast(error)); } + getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace; + getBE().compositionInfo.hwc.hdrMetadata = getDrawingHdrMetadata(); + getBE().compositionInfo.hwc.supportedPerFrameMetadata = display->getSupportedPerFrameMetadata(); setHwcLayerBuffer(display); } diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 6dd29ba316..dc908d253c 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -353,6 +353,9 @@ void BufferQueueLayer::setHwcLayerBuffer(const sp& display) getBE().compositionInfo.mBuffer->handle, to_string(error).c_str(), static_cast(error)); } + getBE().compositionInfo.mBufferSlot = mActiveBufferSlot; + getBE().compositionInfo.mBuffer = mActiveBuffer; + getBE().compositionInfo.hwc.fence = acquireFence; } // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 7eeaabb886..f8bb94ea90 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -89,6 +89,7 @@ void ColorLayer::setPerFrameData(const sp& display) { to_string(error).c_str(), static_cast(error)); visible.dump(LOG_TAG); } + getBE().compositionInfo.hwc.visibleRegion = visible; setCompositionType(displayId, HWC2::Composition::SolidColor); @@ -97,6 +98,7 @@ void ColorLayer::setPerFrameData(const sp& display) { ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace, to_string(error).c_str(), static_cast(error)); } + getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace; half4 color = getColor(); error = hwcLayer->setColor({static_cast(std::round(255.0f * color.r)), @@ -106,6 +108,9 @@ void ColorLayer::setPerFrameData(const sp& display) { ALOGE("[%s] Failed to set color: %s (%d)", mName.string(), to_string(error).c_str(), static_cast(error)); } + getBE().compositionInfo.hwc.color = { static_cast(std::round(255.0f * color.r)), + static_cast(std::round(255.0f * color.g)), + static_cast(std::round(255.0f * color.b)), 255 }; // Clear out the transform, because it doesn't make sense absent a source buffer error = hwcLayer->setTransform(HWC2::Transform::None); @@ -113,6 +118,7 @@ void ColorLayer::setPerFrameData(const sp& display) { ALOGE("[%s] Failed to clear transform: %s (%d)", mName.string(), to_string(error).c_str(), static_cast(error)); } + getBE().compositionInfo.hwc.transform = HWC2::Transform::None; } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f7f3fac934..8e6cf99279 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -516,6 +516,7 @@ void Layer::setGeometry(const sp& display, uint32_t z) { " %s (%d)", mName.string(), to_string(blendMode).c_str(), to_string(error).c_str(), static_cast(error)); + getBE().compositionInfo.hwc.blendMode = blendMode; // apply the layer's transform, followed by the display's global transform // here we're guaranteed that the layer's transform preserves rects @@ -568,6 +569,7 @@ void Layer::setGeometry(const sp& display, uint32_t z) { } else { hwcInfo.displayFrame = transformedFrame; } + getBE().compositionInfo.hwc.displayFrame = transformedFrame; FloatRect sourceCrop = computeCrop(display); error = hwcLayer->setSourceCrop(sourceCrop); @@ -579,6 +581,7 @@ void Layer::setGeometry(const sp& display, uint32_t z) { } else { hwcInfo.sourceCrop = sourceCrop; } + getBE().compositionInfo.hwc.sourceCrop = sourceCrop; float alpha = static_cast(getAlpha()); error = hwcLayer->setPlaneAlpha(alpha); @@ -586,10 +589,12 @@ void Layer::setGeometry(const sp& display, uint32_t z) { "[%s] Failed to set plane alpha %.3f: " "%s (%d)", mName.string(), alpha, to_string(error).c_str(), static_cast(error)); + getBE().compositionInfo.hwc.alpha = alpha; 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(error)); + getBE().compositionInfo.hwc.z = z; int type = s.type; int appId = s.appId; @@ -606,6 +611,9 @@ void Layer::setGeometry(const sp& display, uint32_t z) { ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)", mName.string(), static_cast(error)); + getBE().compositionInfo.hwc.type = type; + getBE().compositionInfo.hwc.appId = appId; + /* * Transformations are applied in this order: * 1) buffer orientation/flip/mirror @@ -642,6 +650,7 @@ void Layer::setGeometry(const sp& display, uint32_t z) { if (orientation & ui::Transform::ROT_INVALID) { // we can only handle simple transformation hwcInfo.forceClientComposition = true; + getBE().mHwcLayers[displayId].compositionType = HWC2::Composition::Client; } else { auto transform = static_cast(orientation); hwcInfo.transform = transform; @@ -651,6 +660,7 @@ void Layer::setGeometry(const sp& display, uint32_t z) { "%s (%d)", mName.string(), to_string(transform).c_str(), to_string(error).c_str(), static_cast(error)); + getBE().compositionInfo.hwc.transform = transform; } } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 6ebd668959..56ed7654f6 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -513,6 +513,14 @@ public: return getBE().mHwcLayers[displayId].layer.get(); } + bool setHwcLayer(int32_t hwcId) { + if (getBE().mHwcLayers.count(hwcId) == 0) { + return false; + } + getBE().compositionInfo.hwc.hwcLayer = getBE().mHwcLayers[hwcId].layer; + return true; + } + // ----------------------------------------------------------------------- void clearWithOpenGL(const RenderArea& renderArea) const; diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 3055621edc..0413a459df 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -55,6 +55,8 @@ struct CompositionInfo { ui::Dataspace dataspace; hwc_color_t color; bool clearClientTarget = false; + bool supportedPerFrameMetadata = false; + HdrMetadata hdrMetadata; } hwc; struct { Mesh* mesh; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 2538945f4d..2b74016f47 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1473,6 +1473,9 @@ void SurfaceFlinger::handleMessageRefresh() { mVsyncModulator.onRefreshed(mHadClientComposition); mLayersWithQueuedFrames.clear(); + for (auto& compositionInfo : getBE().mCompositionInfo) { + compositionInfo.hwc.hwcLayer = nullptr; + } } @@ -1557,6 +1560,19 @@ void SurfaceFlinger::calculateWorkingSet() { } mDrawingState.colorMatrixChanged = false; + getBE().mCompositionInfo.clear(); + + for (const auto& [token, display] : mDisplays) { + for (auto& layer : display->getVisibleLayersSortedByZ()) { + auto displayId = display->getId(); + layer->getBE().compositionInfo.compositionType = layer->getCompositionType(displayId); + if (!layer->setHwcLayer(displayId)) { + ALOGV("Need to create HWCLayer for %s", layer->getName().string()); + } + getBE().mCompositionInfo.push_back(layer->getBE().compositionInfo); + layer->getBE().compositionInfo.hwc.hwcLayer = nullptr; + } + } } void SurfaceFlinger::doDebugFlashRegions(const sp& display, bool repaintEverything) diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index ff8dfa82d0..c06c74fad2 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -100,6 +100,7 @@ class Layer; class Surface; class SurfaceFlingerBE; class VSyncSource; +struct CompositionInfo; namespace impl { class EventThread; @@ -224,6 +225,8 @@ public: // use to differentiate callbacks from different hardware composer // instances. Each hardware composer instance gets a different sequence id. int32_t mComposerSequenceId; + + std::vector mCompositionInfo; }; -- cgit v1.2.3-59-g8ed1b From 15fb96e63f2de336bb01e0824cc85141e5edfdea Mon Sep 17 00:00:00 2001 From: David Sodman Date: Sun, 7 Jan 2018 10:23:24 -0800 Subject: SF: Track compositionType across displayId's Make sure that compositionType tracks displayId's Bug: 112259502 Test: cts -m CtsViewTestCases SurfaceFlinger_test vrflinger_test Change-Id: I748ef1a6da8257e780daf89af06d76f29d19ad6f --- services/surfaceflinger/Layer.cpp | 8 ++------ services/surfaceflinger/LayerBE.h | 1 + services/surfaceflinger/SurfaceFlinger.cpp | 13 +++++++++---- services/surfaceflinger/SurfaceFlinger.h | 2 +- 4 files changed, 13 insertions(+), 11 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 8e6cf99279..1bb72326d9 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -772,16 +772,12 @@ void Layer::setCompositionType(int32_t displayId, HWC2::Composition type, bool c } HWC2::Composition Layer::getCompositionType(int32_t displayId) const { - if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { + if (getBE().mHwcLayers.count(displayId) == 0) { // If we're querying the composition type for a display that does not // have a HWC counterpart, then it will always be Client return HWC2::Composition::Client; } - if (getBE().mHwcLayers.count(displayId) == 0) { - ALOGE("getCompositionType called with an invalid HWC layer"); - return HWC2::Composition::Invalid; - } - return getBE().mHwcLayers.at(displayId).compositionType; + return getBE().mHwcLayers[displayId].compositionType; } void Layer::setClearClientTarget(int32_t displayId, bool clear) { diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 0413a459df..dacdc06e19 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -40,6 +40,7 @@ struct CompositionInfo { std::shared_ptr layer; struct { std::shared_ptr hwcLayer; + int32_t displayId = -1; sp fence; HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid; Rect displayFrame; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c0c684a502..8cee8d7801 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1464,8 +1464,11 @@ void SurfaceFlinger::handleMessageRefresh() { mVsyncModulator.onRefreshed(mHadClientComposition); mLayersWithQueuedFrames.clear(); - for (auto& compositionInfo : getBE().mCompositionInfo) { - compositionInfo.hwc.hwcLayer = nullptr; + for (const auto& [token, display] : mDisplays) { + const auto displayId = display->getId(); + for (auto& compositionInfo : getBE().mCompositionInfo[displayId]) { + compositionInfo.hwc.hwcLayer = nullptr; + } } } @@ -1551,16 +1554,18 @@ void SurfaceFlinger::calculateWorkingSet() { } mDrawingState.colorMatrixChanged = false; - getBE().mCompositionInfo.clear(); for (const auto& [token, display] : mDisplays) { + const auto displayId = display->getId(); + getBE().mCompositionInfo[displayId].clear(); for (auto& layer : display->getVisibleLayersSortedByZ()) { auto displayId = display->getId(); layer->getBE().compositionInfo.compositionType = layer->getCompositionType(displayId); if (!layer->setHwcLayer(displayId)) { ALOGV("Need to create HWCLayer for %s", layer->getName().string()); } - getBE().mCompositionInfo.push_back(layer->getBE().compositionInfo); + layer->getBE().compositionInfo.hwc.displayId = displayId; + getBE().mCompositionInfo[displayId].push_back(layer->getBE().compositionInfo); layer->getBE().compositionInfo.hwc.hwcLayer = nullptr; } } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c06c74fad2..bdbd6ab750 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -226,7 +226,7 @@ public: // instances. Each hardware composer instance gets a different sequence id. int32_t mComposerSequenceId; - std::vector mCompositionInfo; + std::unordered_map> mCompositionInfo; }; -- cgit v1.2.3-59-g8ed1b From 7e4ae11fd91210a1965154bbfb53d8d4811d37c2 Mon Sep 17 00:00:00 2001 From: David Sodman Date: Fri, 9 Feb 2018 15:02:28 -0800 Subject: SF: Add frame-composition info dumping Add frame-composition info as part of command-line option and as part of dumpAll Bug: 112259502 Test: manual test Change-Id: I8dbb4d31918415779f909df658a3c7f32b11452d --- services/surfaceflinger/Layer.cpp | 6 ++ services/surfaceflinger/LayerBE.cpp | 115 ++++++++++++++++++++--------- services/surfaceflinger/LayerBE.h | 5 +- services/surfaceflinger/SurfaceFlinger.cpp | 44 ++++++++++- services/surfaceflinger/SurfaceFlinger.h | 2 + 5 files changed, 135 insertions(+), 37 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 1bb72326d9..1a2566eccb 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1533,6 +1533,12 @@ void Layer::miniDump(String8& result, int32_t displayId) const { 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.append("- - - - - - - - - - - - - - - -\n"); + + std::string compositionInfoStr; + getBE().compositionInfo.dump(compositionInfoStr, "compositionInfo"); + result.append(compositionInfoStr.c_str()); + result.append("- - - - - - - - - - - - - - - -"); result.append("- - - - - - - - - - - - - - - -"); result.append("- - - - - - - - - - - - - - -\n"); diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp index b936b3f6a9..6381a44ba8 100644 --- a/services/surfaceflinger/LayerBE.cpp +++ b/services/surfaceflinger/LayerBE.cpp @@ -20,6 +20,11 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "Layer.h" +#include "RenderEngine/RenderEngine.h" + +#include "android-base/stringprintf.h" + +#include namespace android { @@ -41,50 +46,94 @@ void LayerBE::onLayerDisplayed(const sp& releaseFence) { mLayer->onLayerDisplayed(releaseFence); } -void CompositionInfo::dumpHwc(const char* tag) const { - ALOGV("[%s]\thwcLayer=%p", tag, hwc.hwcLayer.get()); - ALOGV("[%s]\tfence=%p", tag, hwc.fence.get()); - ALOGV("[%s]\ttransform=%d", tag, hwc.transform); - ALOGV("[%s]\tz=%d", tag, hwc.z); - ALOGV("[%s]\ttype=%d", tag, hwc.type); - ALOGV("[%s]\tappId=%d", tag, hwc.appId); - ALOGV("[%s]\tdisplayFrame=%4d %4d %4d %4d", tag, hwc.displayFrame.left, hwc.displayFrame.top, hwc.displayFrame.right, hwc.displayFrame.bottom); - ALOGV("[%s]\talpha=%.3f", tag, hwc.alpha); - ALOGV("[%s]\tsourceCrop=%6.1f %6.1f %6.1f %6.1f", tag, hwc.sourceCrop.left, hwc.sourceCrop.top, hwc.sourceCrop.right, hwc.sourceCrop.bottom); - - std::string label = tag; - label+=":visibleRegion"; - hwc.visibleRegion.dump(label.c_str()); - label = tag; - label+=":surfaceDamage"; - hwc.surfaceDamage.dump(label.c_str()); +void CompositionInfo::dump(const char* tag) const +{ + std::string logString; + dump(logString, tag); + ALOGV("%s", logString.c_str()); } -void CompositionInfo::dumpRe(const char* tag) const { - ALOGV("[%s]\tblackoutLayer=%d", tag, re.blackoutLayer); - ALOGV("[%s]\tclearArea=%d", tag, re.clearArea); - ALOGV("[%s]\tpreMultipliedAlpha=%d", tag, re.preMultipliedAlpha); - ALOGV("[%s]\topaque=%d", tag, re.opaque); - ALOGV("[%s]\tdisableTexture=%d", tag, re.disableTexture); - ALOGV("[%s]\ttexture:name(%d), target(%d), size(%d/%d)", tag, re.texture.getTextureName(), re.texture.getTextureTarget(), (unsigned int)re.texture.getWidth(), (unsigned int)re.texture.getHeight()); - ALOGV("[%s]\tuseIdentityTransform=%d\n", tag, re.useIdentityTransform); +void CompositionInfo::dumpHwc(std::string& result, const char* tag) const { + if (tag == nullptr) { + result += base::StringPrintf("HWC parameters\n"); + } else { + result += base::StringPrintf("[%s]HWC parameters\n", tag); + } + + result += base::StringPrintf("\thwcLayer=%p\n", static_cast(&*hwc.hwcLayer)); + result += base::StringPrintf("\tfence=%p\n", hwc.fence.get()); + result += base::StringPrintf("\tblendMode=%d\n", hwc.blendMode); + result += base::StringPrintf("\ttransform=%d\n", hwc.transform); + result += base::StringPrintf("\tz=%d\n", hwc.z); + result += base::StringPrintf("\ttype=%d\n", hwc.type); + result += base::StringPrintf("\tappId=%d\n", hwc.appId); + result += base::StringPrintf("\tdisplayFrame=%4d %4d %4d %4d\n", hwc.displayFrame.left, hwc.displayFrame.top, hwc.displayFrame.right, hwc.displayFrame.bottom); + result += base::StringPrintf("\talpha=%.3f", hwc.alpha); + result += base::StringPrintf("\tsourceCrop=%6.1f %6.1f %6.1f %6.1f\n", hwc.sourceCrop.left, hwc.sourceCrop.top, hwc.sourceCrop.right, hwc.sourceCrop.bottom); + + { + // + // Keep a conversion from std::string to String8 and back until Region can use std::string + // + String8 regionString; + hwc.visibleRegion.dump(regionString, "visibleRegion"); + hwc.surfaceDamage.dump(regionString, "surfaceDamage"); + result += regionString.string(); + } } -void CompositionInfo::dump(const char* tag) const { - ALOGV("[%s] CompositionInfo", tag); - ALOGV("[%s]\tLayerName: %s", tag, layerName.c_str()); - ALOGV("[%s]\tCompositionType: %d", tag, compositionType); - ALOGV("[%s]\tmBuffer = %p", tag, mBuffer.get()); - ALOGV("[%s]\tmBufferSlot=%d", tag, mBufferSlot); +void CompositionInfo::dumpRe(std::string& result, const char* tag) const { + if (tag == nullptr) { + result += base::StringPrintf("RenderEngine parameters:\n"); + } else { + result += base::StringPrintf("[%s]RenderEngine parameters:\n", tag); + } + + Mesh& mesh = layer->getMesh(); + result += base::StringPrintf("\tblackoutLayer=%d\n", re.blackoutLayer); + result += base::StringPrintf("\tclearArea=%d\n", re.clearArea); + result += base::StringPrintf("\tpreMultipliedAlpha=%d\n", re.preMultipliedAlpha); + result += base::StringPrintf("\topaque=%d\n", re.opaque); + result += base::StringPrintf("\tdisableTexture=%d\n", re.disableTexture); + result += base::StringPrintf("\ttexture:name(%d), target(%d), size(%d/%d)\n", re.texture.getTextureName(), re.texture.getTextureTarget(), (unsigned int)re.texture.getWidth(), (unsigned int)re.texture.getHeight()); + result += base::StringPrintf("\tuseIdentityTransform=%d\n", re.useIdentityTransform); + Mesh::VertexArray positions(mesh.getPositionArray()); + result += base::StringPrintf("\tpositions[(%6.1f,%6.1f), (%6.1f,%6.1f), (%6.1f,%6.1f), (%6.1f,%6.1f)]\n", + positions[0][0], positions[0][1], positions[1][0], positions[1][1], + positions[2][0], positions[2][1], positions[3][0], positions[3][1]); + Mesh::VertexArray texCoords(mesh.getTexCoordArray()); + result += base::StringPrintf("\ttexCoords[(%6.1f,%6.1f), (%6.1f,%6.1f),(%6.1f,%6.1f),(%6.1f,%6.1f)]\n", + texCoords[0][0], texCoords[0][1], texCoords[1][0], texCoords[1][1], + texCoords[2][0], texCoords[2][1], texCoords[3][0], texCoords[3][1]); +} + +void CompositionInfo::dump(std::string& result, const char* tag) const +{ + if (tag == nullptr) { + result += base::StringPrintf("CompositionInfo\n"); + } else { + result += base::StringPrintf("[%s]CompositionInfo\n", tag); + } + result += base::StringPrintf("\tLayerName: %s\n", layerName.c_str()); + result += base::StringPrintf("\tCompositionType: %d\n", compositionType); + result += base::StringPrintf("\tmBuffer = %p\n", mBuffer.get()); + result += base::StringPrintf("\tmBufferSlot=%d\n", mBufferSlot); + result += base::StringPrintf("\tdisplayFrame=%4d %4d %4d %4d\n", hwc.displayFrame.left, hwc.displayFrame.top, hwc.displayFrame.right, hwc.displayFrame.bottom); + result += base::StringPrintf("\talpha=%f\n", hwc.alpha); + result += base::StringPrintf("\tsourceCrop=%6.1f %6.1f %6.1f %6.1f\n", hwc.sourceCrop.left, hwc.sourceCrop.top, hwc.sourceCrop.right, hwc.sourceCrop.bottom); + switch (compositionType) { case HWC2::Composition::Device: - dumpHwc(tag); + dumpHwc(result, tag); break; case HWC2::Composition::Client: - dumpRe(tag); + dumpRe(result, tag); + break; default: break; } } + + }; // namespace android diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index dacdc06e19..86d4ac4865 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -73,8 +73,9 @@ struct CompositionInfo { } re; void dump(const char* tag) const; - void dumpHwc(const char* tag) const; - void dumpRe(const char* tag) const; + void dump(std::string& result, const char* tag = nullptr) const; + void dumpHwc(std::string& result, const char* tag = nullptr) const; + void dumpRe(std::string& result, const char* tag = nullptr) const; }; class LayerBE { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 8cee8d7801..4df62afb2c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -91,6 +91,8 @@ #include +#include "android-base/stringprintf.h" + #include #include #include @@ -1463,13 +1465,15 @@ void SurfaceFlinger::handleMessageRefresh() { mVsyncModulator.onRefreshed(mHadClientComposition); - mLayersWithQueuedFrames.clear(); + getBE().mEndOfFrameCompositionInfo = std::move(getBE().mCompositionInfo); for (const auto& [token, display] : mDisplays) { const auto displayId = display->getId(); - for (auto& compositionInfo : getBE().mCompositionInfo[displayId]) { + for (auto& compositionInfo : getBE().mEndOfFrameCompositionInfo[displayId]) { compositionInfo.hwc.hwcLayer = nullptr; } } + + mLayersWithQueuedFrames.clear(); } @@ -3910,6 +3914,13 @@ status_t SurfaceFlinger::doDump(int fd, const Vector& args, bool asPro dumpAll = false; } + if ((index < numArgs) && + (args[index] == String16("--frame-composition"))) { + index++; + dumpFrameCompositionInfo(result); + dumpAll = false; + } + if ((index < numArgs) && (args[index] == String16("--display-identification"))) { index++; @@ -4167,6 +4178,31 @@ void SurfaceFlinger::dumpWideColorInfo(String8& result) const { result.append("\n"); } +void SurfaceFlinger::dumpFrameCompositionInfo(String8& result) const { + std::string stringResult; + + for (const auto& [token, display] : mDisplays) { + const auto displayId = display->getId(); + if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { + continue; + } + + const auto& compositionInfoIt = getBE().mEndOfFrameCompositionInfo.find(displayId); + if (compositionInfoIt == getBE().mEndOfFrameCompositionInfo.end()) { + break; + } + const auto& compositionInfoList = compositionInfoIt->second; + stringResult += base::StringPrintf("Display: %d\n", displayId); + stringResult += base::StringPrintf("numComponents: %zu\n", compositionInfoList.size()); + for (const auto& compositionInfo : compositionInfoList) { + compositionInfo.dump(stringResult, nullptr); + stringResult += base::StringPrintf("\n"); + } + } + + result.append(stringResult.c_str()); +} + LayersProto SurfaceFlinger::dumpProtoInfo(LayerVector::StateSet stateSet) const { LayersProto layersProto; const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; @@ -4293,6 +4329,10 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, result.append(LayerProtoParser::layersToString(std::move(layerTree)).c_str()); result.append("\n"); + result.append("\nFrame-Composition information:\n"); + dumpFrameCompositionInfo(result); + result.append("\n"); + /* * Dump Display state */ diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index bdbd6ab750..572f5d003b 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -227,6 +227,7 @@ public: int32_t mComposerSequenceId; std::unordered_map> mCompositionInfo; + std::unordered_map> mEndOfFrameCompositionInfo; }; @@ -753,6 +754,7 @@ private: void dumpBufferingStats(String8& result) const; void dumpDisplayIdentificationData(String8& result) const; void dumpWideColorInfo(String8& result) const; + void dumpFrameCompositionInfo(String8& result) const; LayersProto dumpProtoInfo(LayerVector::StateSet stateSet) const; LayersProto dumpVisibleLayersProtoInfo(const DisplayDevice& display) const; -- cgit v1.2.3-59-g8ed1b From cbc184fba2ab0948ba031d45c265bb4a7cb6db22 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Wed, 22 Aug 2018 13:24:10 -0700 Subject: [RenderEngine] Add Android.bp to RenderEngine Besides make RenderEngine as static library, this patch also intentionally moves all header files to public includable directory. The header files will be structured better in the progress of stripping off GL implementation out of public interfaces. BUG: 112585051 Test: Build, flash and do display validation Change-Id: Ife6e27896a2ccee6a23781a43ebc508e2587eb71 --- services/surfaceflinger/Android.bp | 12 +- services/surfaceflinger/BufferLayer.cpp | 2 +- services/surfaceflinger/BufferLayer.h | 5 +- services/surfaceflinger/BufferLayerConsumer.cpp | 7 +- services/surfaceflinger/BufferStateLayer.cpp | 2 +- services/surfaceflinger/BufferStateLayer.h | 5 +- services/surfaceflinger/ColorLayer.cpp | 5 +- services/surfaceflinger/DisplayDevice.cpp | 23 +- services/surfaceflinger/DisplayDevice.h | 2 +- services/surfaceflinger/Layer.cpp | 2 +- services/surfaceflinger/Layer.h | 27 +-- services/surfaceflinger/LayerBE.cpp | 4 +- services/surfaceflinger/LayerBE.h | 7 +- services/surfaceflinger/RenderEngine/Android.bp | 75 ++++++ .../surfaceflinger/RenderEngine/Description.cpp | 4 +- services/surfaceflinger/RenderEngine/Description.h | 99 -------- .../RenderEngine/GLES20RenderEngine.cpp | 16 +- .../RenderEngine/GLES20RenderEngine.h | 122 ---------- .../surfaceflinger/RenderEngine/GLExtensions.cpp | 4 +- .../surfaceflinger/RenderEngine/GLExtensions.h | 88 ------- services/surfaceflinger/RenderEngine/Image.cpp | 6 +- services/surfaceflinger/RenderEngine/Image.h | 60 ----- services/surfaceflinger/RenderEngine/Mesh.cpp | 2 +- services/surfaceflinger/RenderEngine/Mesh.h | 101 -------- services/surfaceflinger/RenderEngine/Program.cpp | 10 +- services/surfaceflinger/RenderEngine/Program.h | 91 -------- .../surfaceflinger/RenderEngine/ProgramCache.cpp | 9 +- .../surfaceflinger/RenderEngine/ProgramCache.h | 197 ---------------- .../surfaceflinger/RenderEngine/RenderEngine.cpp | 21 +- .../surfaceflinger/RenderEngine/RenderEngine.h | 255 --------------------- services/surfaceflinger/RenderEngine/Surface.cpp | 5 +- services/surfaceflinger/RenderEngine/Surface.h | 95 -------- services/surfaceflinger/RenderEngine/Texture.cpp | 4 +- services/surfaceflinger/RenderEngine/Texture.h | 56 ----- .../include/renderengine/Description.h | 99 ++++++++ .../include/renderengine/GLES20RenderEngine.h | 121 ++++++++++ .../include/renderengine/GLExtensions.h | 88 +++++++ .../RenderEngine/include/renderengine/Image.h | 60 +++++ .../RenderEngine/include/renderengine/Mesh.h | 101 ++++++++ .../RenderEngine/include/renderengine/Program.h | 90 ++++++++ .../include/renderengine/ProgramCache.h | 195 ++++++++++++++++ .../include/renderengine/RenderEngine.h | 255 +++++++++++++++++++++ .../RenderEngine/include/renderengine/Surface.h | 95 ++++++++ .../RenderEngine/include/renderengine/Texture.h | 56 +++++ services/surfaceflinger/SurfaceFlinger.cpp | 3 +- services/surfaceflinger/tests/fakehwc/Android.bp | 3 +- .../unittests/mock/RenderEngine/MockRenderEngine.h | 10 +- 47 files changed, 1321 insertions(+), 1278 deletions(-) create mode 100644 services/surfaceflinger/RenderEngine/Android.bp delete mode 100644 services/surfaceflinger/RenderEngine/Description.h delete mode 100644 services/surfaceflinger/RenderEngine/GLES20RenderEngine.h delete mode 100644 services/surfaceflinger/RenderEngine/GLExtensions.h delete mode 100644 services/surfaceflinger/RenderEngine/Image.h delete mode 100644 services/surfaceflinger/RenderEngine/Mesh.h delete mode 100644 services/surfaceflinger/RenderEngine/Program.h delete mode 100644 services/surfaceflinger/RenderEngine/ProgramCache.h delete mode 100644 services/surfaceflinger/RenderEngine/RenderEngine.h delete mode 100644 services/surfaceflinger/RenderEngine/Surface.h delete mode 100644 services/surfaceflinger/RenderEngine/Texture.h create mode 100644 services/surfaceflinger/RenderEngine/include/renderengine/Description.h create mode 100644 services/surfaceflinger/RenderEngine/include/renderengine/GLES20RenderEngine.h create mode 100644 services/surfaceflinger/RenderEngine/include/renderengine/GLExtensions.h create mode 100644 services/surfaceflinger/RenderEngine/include/renderengine/Image.h create mode 100644 services/surfaceflinger/RenderEngine/include/renderengine/Mesh.h create mode 100644 services/surfaceflinger/RenderEngine/include/renderengine/Program.h create mode 100644 services/surfaceflinger/RenderEngine/include/renderengine/ProgramCache.h create mode 100644 services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h create mode 100644 services/surfaceflinger/RenderEngine/include/renderengine/Surface.h create mode 100644 services/surfaceflinger/RenderEngine/include/renderengine/Texture.h (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index ee69b8326e..05535a520d 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -55,6 +55,7 @@ cc_defaults { "libvulkan", ], static_libs: [ + "librenderengine", "libserviceutils", "libtrace_proto", "libvkjson", @@ -66,6 +67,7 @@ cc_defaults { "android.hardware.graphics.composer@2.2-command-buffer", ], export_static_lib_headers: [ + "librenderengine", "libserviceutils", ], export_shared_lib_headers: [ @@ -118,16 +120,6 @@ filegroup { "LayerVector.cpp", "MonitoredProducer.cpp", "RenderArea.cpp", - "RenderEngine/Description.cpp", - "RenderEngine/GLES20RenderEngine.cpp", - "RenderEngine/GLExtensions.cpp", - "RenderEngine/Image.cpp", - "RenderEngine/Mesh.cpp", - "RenderEngine/Program.cpp", - "RenderEngine/ProgramCache.cpp", - "RenderEngine/RenderEngine.cpp", - "RenderEngine/Surface.cpp", - "RenderEngine/Texture.cpp", "Scheduler/DispSync.cpp", "Scheduler/DispSyncSource.cpp", "Scheduler/EventControlThread.cpp", diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index f48aa47962..d0ccabbe4b 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -24,7 +24,7 @@ #include "DisplayDevice.h" #include "LayerRejecter.h" -#include "RenderEngine/RenderEngine.h" +#include #include #include diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 0b641b731f..3319a98025 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -24,13 +24,12 @@ #include "FrameTracker.h" #include "LayerVector.h" #include "MonitoredProducer.h" -#include "RenderEngine/Mesh.h" -#include "RenderEngine/Texture.h" #include "SurfaceFlinger.h" #include #include - +#include +#include #include #include #include diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp index 9096d4c719..aa8f4e1dc6 100644 --- a/services/surfaceflinger/BufferLayerConsumer.cpp +++ b/services/surfaceflinger/BufferLayerConsumer.cpp @@ -20,10 +20,7 @@ //#define LOG_NDEBUG 0 #include "BufferLayerConsumer.h" - #include "Layer.h" -#include "RenderEngine/Image.h" -#include "RenderEngine/RenderEngine.h" #include "Scheduler/DispSync.h" #include @@ -38,9 +35,9 @@ #include #include #include - #include - +#include +#include #include #include #include diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 369ad89e53..da9dcfbb05 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -20,9 +20,9 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "BufferStateLayer.h" -#include "RenderEngine/Image.h" #include +#include namespace android { diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index e492375837..038eb01209 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -16,13 +16,12 @@ #pragma once -#include "RenderEngine/Image.h" -#include "RenderEngine/RenderEngine.h" - #include "BufferLayer.h" #include "Layer.h" #include +#include +#include #include #include diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index f8bb94ea90..c29698b823 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -22,14 +22,13 @@ #include #include +#include +#include #include #include -#include - #include "ColorLayer.h" #include "DisplayDevice.h" -#include "RenderEngine/RenderEngine.h" #include "SurfaceFlinger.h" namespace android { diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 776b84ae0b..0fbd4594f8 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -18,6 +18,8 @@ #undef LOG_TAG #define LOG_TAG "DisplayDevice" +#include "DisplayDevice.h" + #include #include @@ -26,31 +28,24 @@ #include #include +#include +#include #include - -#include -#include - +#include +#include +#include #include #include #include - -#include - -#include +#include +#include #include "DisplayHardware/DisplaySurface.h" #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/HWC2.h" -#include "RenderEngine/RenderEngine.h" - -#include "DisplayDevice.h" #include "SurfaceFlinger.h" #include "Layer.h" -#include -#include - namespace android { // retrieve triple buffer setting from configstore diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index bcb2976998..da0931e43f 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -37,7 +38,6 @@ #include #include "RenderArea.h" -#include "RenderEngine/Surface.h" struct ANativeWindow; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 1a2566eccb..4f0b212129 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -53,7 +53,7 @@ #include "DisplayHardware/HWComposer.h" -#include "RenderEngine/RenderEngine.h" +#include #include #include "LayerProtoHelper.h" diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 56ed7654f6..443f410fe7 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -19,23 +19,26 @@ #include -#include -#include -#include - +#include +#include +#include +#include +#include +#include +#include #include #include #include #include #include #include +#include +#include +#include -#include -#include -#include - -#include #include +#include +#include #include "Client.h" #include "FrameTracker.h" @@ -45,15 +48,9 @@ #include "SurfaceFlinger.h" #include "TimeStats/TimeStats.h" -#include #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/HWComposerBufferCache.h" #include "RenderArea.h" -#include "RenderEngine/Mesh.h" -#include "RenderEngine/Texture.h" - -#include -#include using namespace android::surfaceflinger; diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp index 6381a44ba8..3e04f266af 100644 --- a/services/surfaceflinger/LayerBE.cpp +++ b/services/surfaceflinger/LayerBE.cpp @@ -20,9 +20,9 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "Layer.h" -#include "RenderEngine/RenderEngine.h" -#include "android-base/stringprintf.h" +#include +#include #include diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 86d4ac4865..e5110b7bea 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -19,14 +19,13 @@ #include #include +#include +#include #include -#include "SurfaceFlinger.h" - #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/HWComposerBufferCache.h" -#include "RenderEngine/Mesh.h" -#include "RenderEngine/Texture.h" +#include "SurfaceFlinger.h" namespace android { diff --git a/services/surfaceflinger/RenderEngine/Android.bp b/services/surfaceflinger/RenderEngine/Android.bp new file mode 100644 index 0000000000..13752f21d4 --- /dev/null +++ b/services/surfaceflinger/RenderEngine/Android.bp @@ -0,0 +1,75 @@ +// TODO(b/112585051) Add to VNDK once moved to libs/ +cc_defaults { + name: "renderengine_defaults", + cflags: [ + "-DLOG_TAG=\"RenderEngine\"", + "-Wall", + "-Werror", + "-Wthread-safety", + "-Wunused", + "-Wunreachable-code", + ], + cppflags: ["-std=c++1z"], +} + +cc_defaults { + name: "librenderengine_defaults", + defaults: ["renderengine_defaults"], + cflags: [ + "-DGL_GLEXT_PROTOTYPES", + "-DEGL_EGLEXT_PROTOTYPES", + ], + shared_libs: [ + "android.hardware.configstore-utils", + "android.hardware.configstore@1.0", + "android.hardware.configstore@1.1", + "android.hardware.configstore@1.2", + "libcutils", + "libEGL", + "libGLESv1_CM", + "libGLESv2", + "libgui", + "liblog", + "libui", + "libutils", + ], + local_include_dirs: ["include"], + export_include_dirs: ["include"], +} + +filegroup { + name: "librenderengine_sources", + srcs: [ + "Description.cpp", + "GLES20RenderEngine.cpp", + "GLExtensions.cpp", + "Image.cpp", + "Mesh.cpp", + "Program.cpp", + "ProgramCache.cpp", + "RenderEngine.cpp", + "Surface.cpp", + "Texture.cpp", + ], +} + +cc_library_static { + name: "librenderengine", + defaults: ["librenderengine_defaults"], + double_loadable: true, + + clang: true, + cflags: [ + "-fvisibility=hidden", + "-Werror=format", + ], + cppflags: [ + "-fwhole-program-vtables", // requires ThinLTO + ], + srcs: [ + ":librenderengine_sources", + ], + lto: { + thin: true, + }, +} diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp index d4a2bb4356..d5f2103537 100644 --- a/services/surfaceflinger/RenderEngine/Description.cpp +++ b/services/surfaceflinger/RenderEngine/Description.cpp @@ -14,13 +14,13 @@ * limitations under the License. */ +#include + #include #include #include -#include "Description.h" - namespace android { void Description::setPremultipliedAlpha(bool premultipliedAlpha) { diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h deleted file mode 100644 index 6ebb34018d..0000000000 --- a/services/surfaceflinger/RenderEngine/Description.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2013 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. - */ - -#include -#include "Texture.h" - -#ifndef SF_RENDER_ENGINE_DESCRIPTION_H_ -#define SF_RENDER_ENGINE_DESCRIPTION_H_ - -namespace android { - -class Program; - -/* - * This holds the state of the rendering engine. This class is used - * to generate a corresponding GLSL program and set the appropriate - * uniform. - * - * Program and ProgramCache are friends and access the state directly - */ -class Description { -public: - Description() = default; - ~Description() = default; - - void setPremultipliedAlpha(bool premultipliedAlpha); - void setOpaque(bool opaque); - void setTexture(const Texture& texture); - void disableTexture(); - void setColor(const half4& color); - void setProjectionMatrix(const mat4& mtx); - void setColorMatrix(const mat4& mtx); - void setInputTransformMatrix(const mat3& matrix); - void setOutputTransformMatrix(const mat4& matrix); - bool hasInputTransformMatrix() const; - bool hasOutputTransformMatrix() const; - bool hasColorMatrix() const; - const mat4& getColorMatrix() const; - - void setY410BT2020(bool enable); - - enum class TransferFunction : int { - LINEAR, - SRGB, - ST2084, - HLG, // Hybrid Log-Gamma for HDR. - }; - void setInputTransferFunction(TransferFunction transferFunction); - void setOutputTransferFunction(TransferFunction transferFunction); - void setDisplayMaxLuminance(const float maxLuminance); - -private: - friend class Program; - friend class ProgramCache; - - // whether textures are premultiplied - bool mPremultipliedAlpha = false; - // whether this layer is marked as opaque - bool mOpaque = true; - - // Texture this layer uses - Texture mTexture; - bool mTextureEnabled = false; - - // color used when texturing is disabled or when setting alpha. - half4 mColor; - - // true if the sampled pixel values are in Y410/BT2020 rather than RGBA - bool mY410BT2020 = false; - - // transfer functions for the input/output - TransferFunction mInputTransferFunction = TransferFunction::LINEAR; - TransferFunction mOutputTransferFunction = TransferFunction::LINEAR; - - float mDisplayMaxLuminance; - - // projection matrix - mat4 mProjectionMatrix; - mat4 mColorMatrix; - mat3 mInputTransformMatrix; - mat4 mOutputTransformMatrix; -}; - -} /* namespace android */ - -#endif /* SF_RENDER_ENGINE_DESCRIPTION_H_ */ diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index 136d12f6dc..617ba76197 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -19,26 +19,24 @@ #define LOG_TAG "RenderEngine" #define ATRACE_TAG ATRACE_TAG_GRAPHICS +#include + #include #include - +#include +#include +#include +#include +#include #include #include #include - #include #include #include #include -#include "Description.h" -#include "GLES20RenderEngine.h" -#include "Mesh.h" -#include "Program.h" -#include "ProgramCache.h" -#include "Texture.h" - #include #include diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h deleted file mode 100644 index d8cb73b240..0000000000 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2013 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. - */ - -#ifndef SF_GLES20RENDERENGINE_H_ -#define SF_GLES20RENDERENGINE_H_ - -#include -#include - -#include - -#include "Description.h" -#include "ProgramCache.h" -#include "RenderEngine.h" - -// --------------------------------------------------------------------------- -namespace android { -// --------------------------------------------------------------------------- - -class String8; -class Mesh; -class Texture; - -namespace RE { -namespace impl { - -class GLES20RenderEngine : public RenderEngine { - GLuint mProtectedTexName; - GLint mMaxViewportDims[2]; - GLint mMaxTextureSize; - GLuint mVpWidth; - GLuint mVpHeight; - - struct Group { - GLuint texture; - GLuint fbo; - GLuint width; - GLuint height; - mat4 colorTransform; - }; - - Description mState; - Vector mGroupStack; - - virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, - uint32_t* status); - virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName); - -public: - GLES20RenderEngine(uint32_t featureFlags); // See RenderEngine::FeatureFlag - virtual ~GLES20RenderEngine(); - -protected: - virtual void dump(String8& result); - virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, - bool yswap, ui::Transform::orientation_flags rotation); - virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture, - const half4& color) override; - - // Color management related functions and state - void setSourceY410BT2020(bool enable) override; - void setSourceDataSpace(ui::Dataspace source) override; - void setOutputDataSpace(ui::Dataspace dataspace) override; - void setDisplayMaxLuminance(const float maxLuminance) override; - - virtual void setupLayerTexturing(const Texture& texture); - virtual void setupLayerBlackedOut(); - virtual void setupFillWithColor(float r, float g, float b, float a); - virtual void setupColorTransform(const mat4& colorTransform); - virtual void disableTexturing(); - virtual void disableBlending(); - - virtual void drawMesh(const Mesh& mesh); - - virtual size_t getMaxTextureSize() const; - virtual size_t getMaxViewportDims() const; - - // Current dataspace of layer being rendered - ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN; - - // Current output dataspace of the render engine - ui::Dataspace mOutputDataSpace = ui::Dataspace::UNKNOWN; - - // Whether device supports color management, currently color management - // supports sRGB, DisplayP3 color spaces. - const bool mUseColorManagement = false; - mat4 mSrgbToDisplayP3; - mat4 mDisplayP3ToSrgb; - mat3 mSrgbToXyz; - mat3 mBt2020ToXyz; - mat3 mDisplayP3ToXyz; - mat4 mXyzToSrgb; - mat4 mXyzToDisplayP3; - mat4 mXyzToBt2020; - -private: - // A data space is considered HDR data space if it has BT2020 color space - // with PQ or HLG transfer function. - bool isHdrDataSpace(const ui::Dataspace dataSpace) const; - bool needsXYZTransformMatrix() const; -}; - -// --------------------------------------------------------------------------- -} // namespace impl -} // namespace RE -} // namespace android -// --------------------------------------------------------------------------- - -#endif /* SF_GLES20RENDERENGINE_H_ */ diff --git a/services/surfaceflinger/RenderEngine/GLExtensions.cpp b/services/surfaceflinger/RenderEngine/GLExtensions.cpp index 23480b412e..b4fb2a1c55 100644 --- a/services/surfaceflinger/RenderEngine/GLExtensions.cpp +++ b/services/surfaceflinger/RenderEngine/GLExtensions.cpp @@ -14,12 +14,12 @@ * limitations under the License. */ +#include + #include #include #include -#include "GLExtensions.h" - namespace android { // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/RenderEngine/GLExtensions.h b/services/surfaceflinger/RenderEngine/GLExtensions.h deleted file mode 100644 index a6a5053f89..0000000000 --- a/services/surfaceflinger/RenderEngine/GLExtensions.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2010 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. - */ - -#ifndef ANDROID_SF_GLEXTENSION_H -#define ANDROID_SF_GLEXTENSION_H - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -namespace android { -// --------------------------------------------------------------------------- - -class GLExtensions : public Singleton { - friend class Singleton; - - bool mHasNoConfigContext = false; - bool mHasNativeFenceSync = false; - bool mHasFenceSync = false; - bool mHasWaitSync = false; - bool mHasProtectedContent = false; - bool mHasContextPriority = false; - - String8 mVendor; - String8 mRenderer; - String8 mVersion; - String8 mExtensions; - SortedVector mExtensionList; - - String8 mEGLVersion; - String8 mEGLExtensions; - SortedVector mEGLExtensionList; - - static SortedVector parseExtensionString(char const* extensions); - - GLExtensions(const GLExtensions&); - GLExtensions& operator=(const GLExtensions&); - -protected: - GLExtensions() = default; - -public: - bool hasNoConfigContext() const { return mHasNoConfigContext; } - bool hasNativeFenceSync() const { return mHasNativeFenceSync; } - bool hasFenceSync() const { return mHasFenceSync; } - bool hasWaitSync() const { return mHasWaitSync; } - bool hasProtectedContent() const { return mHasProtectedContent; } - bool hasContextPriority() const { return mHasContextPriority; } - - void initWithGLStrings(GLubyte const* vendor, GLubyte const* renderer, GLubyte const* version, - GLubyte const* extensions); - char const* getVendor() const; - char const* getRenderer() const; - char const* getVersion() const; - char const* getExtensions() const; - bool hasExtension(char const* extension) const; - - void initWithEGLStrings(char const* eglVersion, char const* eglExtensions); - char const* getEGLVersion() const; - char const* getEGLExtensions() const; - bool hasEGLExtension(char const* extension) const; -}; - -// --------------------------------------------------------------------------- -}; // namespace android - -#endif // ANDROID_SF_GLEXTENSION_H diff --git a/services/surfaceflinger/RenderEngine/Image.cpp b/services/surfaceflinger/RenderEngine/Image.cpp index 6e0a8803e9..ee140eb000 100644 --- a/services/surfaceflinger/RenderEngine/Image.cpp +++ b/services/surfaceflinger/RenderEngine/Image.cpp @@ -14,14 +14,14 @@ * limitations under the License. */ -#include "Image.h" +#include #include #include -#include "GLExtensions.h" -#include "RenderEngine.h" +#include +#include namespace android { namespace RE { diff --git a/services/surfaceflinger/RenderEngine/Image.h b/services/surfaceflinger/RenderEngine/Image.h deleted file mode 100644 index c38fe0a2ff..0000000000 --- a/services/surfaceflinger/RenderEngine/Image.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 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 - -#include -#include - -struct ANativeWindowBuffer; - -namespace android { -namespace RE { - -class Image { -public: - virtual ~Image() = 0; - virtual bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) = 0; -}; - -namespace impl { - -class RenderEngine; - -class Image : public RE::Image { -public: - explicit Image(const RenderEngine& engine); - ~Image() override; - - Image(const Image&) = delete; - Image& operator=(const Image&) = delete; - - bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) override; - -private: - // methods internal to RenderEngine - friend class RenderEngine; - EGLSurface getEGLImage() const { return mEGLImage; } - - EGLDisplay mEGLDisplay; - EGLImageKHR mEGLImage = EGL_NO_IMAGE_KHR; -}; - -} // namespace impl -} // namespace RE -} // namespace android diff --git a/services/surfaceflinger/RenderEngine/Mesh.cpp b/services/surfaceflinger/RenderEngine/Mesh.cpp index 6a62b1d7dd..43852eba33 100644 --- a/services/surfaceflinger/RenderEngine/Mesh.cpp +++ b/services/surfaceflinger/RenderEngine/Mesh.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "Mesh.h" +#include #include diff --git a/services/surfaceflinger/RenderEngine/Mesh.h b/services/surfaceflinger/RenderEngine/Mesh.h deleted file mode 100644 index d0a9ac0c65..0000000000 --- a/services/surfaceflinger/RenderEngine/Mesh.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2013 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. - */ - -#ifndef SF_RENDER_ENGINE_MESH_H -#define SF_RENDER_ENGINE_MESH_H - -#include - -namespace android { - -class Mesh { -public: - enum Primitive { - TRIANGLES = 0x0004, // GL_TRIANGLES - TRIANGLE_STRIP = 0x0005, // GL_TRIANGLE_STRIP - TRIANGLE_FAN = 0x0006 // GL_TRIANGLE_FAN - }; - - Mesh(Primitive primitive, size_t vertexCount, size_t vertexSize, size_t texCoordsSize = 0); - ~Mesh(); - - /* - * VertexArray handles the stride automatically. - */ - template - class VertexArray { - friend class Mesh; - float* mData; - size_t mStride; - VertexArray(float* data, size_t stride) : mData(data), mStride(stride) {} - - public: - TYPE& operator[](size_t index) { return *reinterpret_cast(&mData[index * mStride]); } - TYPE const& operator[](size_t index) const { - return *reinterpret_cast(&mData[index * mStride]); - } - }; - - template - VertexArray getPositionArray() { - return VertexArray(getPositions(), mStride); - } - - template - VertexArray getTexCoordArray() { - return VertexArray(getTexCoords(), mStride); - } - - Primitive getPrimitive() const; - - // returns a pointer to the vertices positions - float const* getPositions() const; - - // returns a pointer to the vertices texture coordinates - float const* getTexCoords() const; - - // number of vertices in this mesh - size_t getVertexCount() const; - - // dimension of vertices - size_t getVertexSize() const; - - // dimension of texture coordinates - size_t getTexCoordsSize() const; - - // return stride in bytes - size_t getByteStride() const; - - // return stride in floats - size_t getStride() const; - -private: - Mesh(const Mesh&); - Mesh& operator=(const Mesh&); - Mesh const& operator=(const Mesh&) const; - - float* getPositions(); - float* getTexCoords(); - float* mVertices; - size_t mVertexCount; - size_t mVertexSize; - size_t mTexCoordsSize; - size_t mStride; - Primitive mPrimitive; -}; - -} /* namespace android */ -#endif /* SF_RENDER_ENGINE_MESH_H */ diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/Program.cpp index fe536f0c7c..87371dc7e7 100644 --- a/services/surfaceflinger/RenderEngine/Program.cpp +++ b/services/surfaceflinger/RenderEngine/Program.cpp @@ -14,15 +14,15 @@ * limitations under the License. */ +#include + #include #include -#include - #include -#include "Description.h" -#include "Program.h" -#include "ProgramCache.h" +#include +#include +#include namespace android { diff --git a/services/surfaceflinger/RenderEngine/Program.h b/services/surfaceflinger/RenderEngine/Program.h deleted file mode 100644 index ae796c5852..0000000000 --- a/services/surfaceflinger/RenderEngine/Program.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2013 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. - */ - -#ifndef SF_RENDER_ENGINE_PROGRAM_H -#define SF_RENDER_ENGINE_PROGRAM_H - -#include - -#include - -#include "Description.h" -#include "ProgramCache.h" - -namespace android { - -class String8; - -/* - * Abstracts a GLSL program comprising a vertex and fragment shader - */ -class Program { -public: - // known locations for position and texture coordinates - enum { position = 0, texCoords = 1 }; - - Program(const ProgramCache::Key& needs, const char* vertex, const char* fragment); - ~Program(); - - /* whether this object is usable */ - bool isValid() const; - - /* Binds this program to the GLES context */ - void use(); - - /* Returns the location of the specified attribute */ - GLuint getAttrib(const char* name) const; - - /* Returns the location of the specified uniform */ - GLint getUniform(const char* name) const; - - /* set-up uniforms from the description */ - void setUniforms(const Description& desc); - -private: - GLuint buildShader(const char* source, GLenum type); - String8& dumpShader(String8& result, GLenum type); - - // whether the initialization succeeded - bool mInitialized; - - // Name of the OpenGL program and shaders - GLuint mProgram; - GLuint mVertexShader; - GLuint mFragmentShader; - - /* location of the projection matrix uniform */ - GLint mProjectionMatrixLoc; - - /* location of the texture matrix uniform */ - GLint mTextureMatrixLoc; - - /* location of the sampler uniform */ - GLint mSamplerLoc; - - /* location of the color uniform */ - GLint mColorLoc; - - /* location of display luminance uniform */ - GLint mDisplayMaxLuminanceLoc; - - /* location of transform matrix */ - GLint mInputTransformMatrixLoc; - GLint mOutputTransformMatrixLoc; -}; - -} /* namespace android */ - -#endif /* SF_RENDER_ENGINE_PROGRAM_H */ diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp index a1d056127e..b7101e05b7 100644 --- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp +++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp @@ -16,16 +16,15 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS +#include + #include #include - +#include +#include #include #include -#include "Description.h" -#include "Program.h" -#include "ProgramCache.h" - namespace android { // ----------------------------------------------------------------------------------------------- diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.h b/services/surfaceflinger/RenderEngine/ProgramCache.h deleted file mode 100644 index 424633e2cc..0000000000 --- a/services/surfaceflinger/RenderEngine/ProgramCache.h +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 2013 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. - */ - -#ifndef SF_RENDER_ENGINE_PROGRAMCACHE_H -#define SF_RENDER_ENGINE_PROGRAMCACHE_H - -#include - -#include -#include -#include - -#include "Description.h" - -namespace android { - -class Description; -class Formatter; -class Program; -class String8; - -/* - * This class generates GLSL programs suitable to handle a given - * Description. It's responsible for figuring out what to - * generate from a Description. - * It also maintains a cache of these Programs. - */ -class ProgramCache : public Singleton { -public: - /* - * Key is used to retrieve a Program in the cache. - * A Key is generated from a Description. - */ - class Key { - friend class ProgramCache; - typedef uint32_t key_t; - key_t mKey; - - public: - enum { - BLEND_SHIFT = 0, - BLEND_MASK = 1 << BLEND_SHIFT, - BLEND_PREMULT = 1 << BLEND_SHIFT, - BLEND_NORMAL = 0 << BLEND_SHIFT, - - OPACITY_SHIFT = 1, - OPACITY_MASK = 1 << OPACITY_SHIFT, - OPACITY_OPAQUE = 1 << OPACITY_SHIFT, - OPACITY_TRANSLUCENT = 0 << OPACITY_SHIFT, - - ALPHA_SHIFT = 2, - ALPHA_MASK = 1 << ALPHA_SHIFT, - ALPHA_LT_ONE = 1 << ALPHA_SHIFT, - ALPHA_EQ_ONE = 0 << ALPHA_SHIFT, - - TEXTURE_SHIFT = 3, - TEXTURE_MASK = 3 << TEXTURE_SHIFT, - TEXTURE_OFF = 0 << TEXTURE_SHIFT, - TEXTURE_EXT = 1 << TEXTURE_SHIFT, - TEXTURE_2D = 2 << TEXTURE_SHIFT, - - INPUT_TRANSFORM_MATRIX_SHIFT = 5, - INPUT_TRANSFORM_MATRIX_MASK = 1 << INPUT_TRANSFORM_MATRIX_SHIFT, - INPUT_TRANSFORM_MATRIX_OFF = 0 << INPUT_TRANSFORM_MATRIX_SHIFT, - INPUT_TRANSFORM_MATRIX_ON = 1 << INPUT_TRANSFORM_MATRIX_SHIFT, - - OUTPUT_TRANSFORM_MATRIX_SHIFT = 6, - OUTPUT_TRANSFORM_MATRIX_MASK = 1 << OUTPUT_TRANSFORM_MATRIX_SHIFT, - OUTPUT_TRANSFORM_MATRIX_OFF = 0 << OUTPUT_TRANSFORM_MATRIX_SHIFT, - OUTPUT_TRANSFORM_MATRIX_ON = 1 << OUTPUT_TRANSFORM_MATRIX_SHIFT, - - INPUT_TF_SHIFT = 7, - INPUT_TF_MASK = 3 << INPUT_TF_SHIFT, - INPUT_TF_LINEAR = 0 << INPUT_TF_SHIFT, - INPUT_TF_SRGB = 1 << INPUT_TF_SHIFT, - INPUT_TF_ST2084 = 2 << INPUT_TF_SHIFT, - INPUT_TF_HLG = 3 << INPUT_TF_SHIFT, - - OUTPUT_TF_SHIFT = 9, - OUTPUT_TF_MASK = 3 << OUTPUT_TF_SHIFT, - OUTPUT_TF_LINEAR = 0 << OUTPUT_TF_SHIFT, - OUTPUT_TF_SRGB = 1 << OUTPUT_TF_SHIFT, - OUTPUT_TF_ST2084 = 2 << OUTPUT_TF_SHIFT, - OUTPUT_TF_HLG = 3 << OUTPUT_TF_SHIFT, - - Y410_BT2020_SHIFT = 11, - Y410_BT2020_MASK = 1 << Y410_BT2020_SHIFT, - Y410_BT2020_OFF = 0 << Y410_BT2020_SHIFT, - Y410_BT2020_ON = 1 << Y410_BT2020_SHIFT, - }; - - inline Key() : mKey(0) {} - inline Key(const Key& rhs) : mKey(rhs.mKey) {} - - inline Key& set(key_t mask, key_t value) { - mKey = (mKey & ~mask) | value; - return *this; - } - - inline bool isTexturing() const { return (mKey & TEXTURE_MASK) != TEXTURE_OFF; } - inline int getTextureTarget() const { return (mKey & TEXTURE_MASK); } - inline bool isPremultiplied() const { return (mKey & BLEND_MASK) == BLEND_PREMULT; } - inline bool isOpaque() const { return (mKey & OPACITY_MASK) == OPACITY_OPAQUE; } - inline bool hasAlpha() const { return (mKey & ALPHA_MASK) == ALPHA_LT_ONE; } - inline bool hasInputTransformMatrix() const { - return (mKey & INPUT_TRANSFORM_MATRIX_MASK) == INPUT_TRANSFORM_MATRIX_ON; - } - inline bool hasOutputTransformMatrix() const { - return (mKey & OUTPUT_TRANSFORM_MATRIX_MASK) == OUTPUT_TRANSFORM_MATRIX_ON; - } - inline bool hasTransformMatrix() const { - return hasInputTransformMatrix() || hasOutputTransformMatrix(); - } - inline int getInputTF() const { return (mKey & INPUT_TF_MASK); } - inline int getOutputTF() const { return (mKey & OUTPUT_TF_MASK); } - - // When HDR and non-HDR contents are mixed, or different types of HDR contents are - // mixed, we will do a tone mapping process to tone map the input content to output - // content. Currently, the following conversions handled, they are: - // * SDR -> HLG - // * SDR -> PQ - // * HLG -> PQ - inline bool needsToneMapping() const { - int inputTF = getInputTF(); - int outputTF = getOutputTF(); - - // Return false when converting from SDR to SDR. - if (inputTF == Key::INPUT_TF_SRGB && outputTF == Key::OUTPUT_TF_LINEAR) { - return false; - } - if (inputTF == Key::INPUT_TF_LINEAR && outputTF == Key::OUTPUT_TF_SRGB) { - return false; - } - - inputTF >>= Key::INPUT_TF_SHIFT; - outputTF >>= Key::OUTPUT_TF_SHIFT; - return inputTF != outputTF; - } - inline bool isY410BT2020() const { return (mKey & Y410_BT2020_MASK) == Y410_BT2020_ON; } - - // this is the definition of a friend function -- not a method of class Needs - friend inline int strictly_order_type(const Key& lhs, const Key& rhs) { - return (lhs.mKey < rhs.mKey) ? 1 : 0; - } - }; - - ProgramCache(); - ~ProgramCache(); - - // Generate shaders to populate the cache - void primeCache(bool useColorManagement); - - // useProgram lookup a suitable program in the cache or generates one - // if none can be found. - void useProgram(const Description& description); - -private: - // compute a cache Key from a Description - static Key computeKey(const Description& description); - // Generate EOTF based from Key. - static void generateEOTF(Formatter& fs, const Key& needs); - // Generate necessary tone mapping methods for OOTF. - static void generateToneMappingProcess(Formatter& fs, const Key& needs); - // Generate OOTF based from Key. - static void generateOOTF(Formatter& fs, const Key& needs); - // Generate OETF based from Key. - static void generateOETF(Formatter& fs, const Key& needs); - // generates a program from the Key - static Program* generateProgram(const Key& needs); - // generates the vertex shader from the Key - static String8 generateVertexShader(const Key& needs); - // generates the fragment shader from the Key - static String8 generateFragmentShader(const Key& needs); - - // Key/Value map used for caching Programs. Currently the cache - // is never shrunk. - DefaultKeyedVector mCache; -}; - -ANDROID_BASIC_TYPES_TRAITS(ProgramCache::Key) - -} /* namespace android */ - -#endif /* SF_RENDER_ENGINE_PROGRAMCACHE_H */ diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index e5dbe2f0a0..594b1eda06 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -14,23 +14,22 @@ * limitations under the License. */ +#include + +#include +#include #include +#include +#include +#include +#include +#include +#include #include #include -#include "GLES20RenderEngine.h" -#include "GLExtensions.h" -#include "Image.h" -#include "Mesh.h" -#include "RenderEngine.h" - -#include #include -#include -#include -#include - using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h deleted file mode 100644 index 6213784f81..0000000000 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright 2013 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. - */ - -#ifndef SF_RENDERENGINE_H_ -#define SF_RENDERENGINE_H_ - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#define EGL_NO_CONFIG ((EGLConfig)0) - -struct ANativeWindowBuffer; - -// --------------------------------------------------------------------------- -namespace android { -// --------------------------------------------------------------------------- - -class String8; -class Rect; -class Region; -class Mesh; -class Texture; - -namespace RE { - -class Image; -class Surface; -class BindNativeBufferAsFramebuffer; - -namespace impl { -class RenderEngine; -} - -class RenderEngine { -public: - enum FeatureFlag { - USE_COLOR_MANAGEMENT = 1 << 0, // Device manages color - }; - - virtual ~RenderEngine() = 0; - - virtual std::unique_ptr createSurface() = 0; - virtual std::unique_ptr createImage() = 0; - - virtual void primeCache() const = 0; - - // dump the extension strings. always call the base class. - virtual void dump(String8& result) = 0; - - virtual bool useNativeFenceSync() const = 0; - virtual bool useWaitSync() const = 0; - - virtual bool isCurrent() const = 0; - virtual bool setCurrentSurface(const RE::Surface& surface) = 0; - virtual void resetCurrentSurface() = 0; - - // helpers - // flush submits RenderEngine command stream for execution and returns a - // native fence fd that is signaled when the execution has completed. It - // returns -1 on errors. - virtual base::unique_fd flush() = 0; - // finish waits until RenderEngine command stream has been executed. It - // returns false on errors. - virtual bool finish() = 0; - // waitFence inserts a wait on an external fence fd to RenderEngine - // command stream. It returns false on errors. - virtual bool waitFence(base::unique_fd fenceFd) = 0; - - virtual void clearWithColor(float red, float green, float blue, float alpha) = 0; - virtual void fillRegionWithColor(const Region& region, uint32_t height, float red, float green, - float blue, float alpha) = 0; - - // common to all GL versions - virtual void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) = 0; - virtual void disableScissor() = 0; - virtual void genTextures(size_t count, uint32_t* names) = 0; - virtual void deleteTextures(size_t count, uint32_t const* names) = 0; - virtual void bindExternalTextureImage(uint32_t texName, const RE::Image& image) = 0; - virtual void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) = 0; - virtual void bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer, - RE::BindNativeBufferAsFramebuffer* bindHelper) = 0; - virtual void unbindNativeBufferAsFrameBuffer(RE::BindNativeBufferAsFramebuffer* bindHelper) = 0; - - // set-up - virtual void checkErrors() const; - virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, - bool yswap, ui::Transform::orientation_flags rotation) = 0; - virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture, - const half4& color) = 0; - virtual void setupLayerTexturing(const Texture& texture) = 0; - virtual void setupLayerBlackedOut() = 0; - virtual void setupFillWithColor(float r, float g, float b, float a) = 0; - - virtual void setupColorTransform(const mat4& /* colorTransform */) = 0; - - virtual void disableTexturing() = 0; - virtual void disableBlending() = 0; - - // HDR and wide color gamut support - virtual void setSourceY410BT2020(bool enable) = 0; - virtual void setSourceDataSpace(ui::Dataspace source) = 0; - virtual void setOutputDataSpace(ui::Dataspace dataspace) = 0; - virtual void setDisplayMaxLuminance(const float maxLuminance) = 0; - - // drawing - virtual void drawMesh(const Mesh& mesh) = 0; - - // queries - virtual size_t getMaxTextureSize() const = 0; - virtual size_t getMaxViewportDims() const = 0; -}; - -class BindNativeBufferAsFramebuffer { -public: - BindNativeBufferAsFramebuffer(RenderEngine& engine, ANativeWindowBuffer* buffer) - : mEngine(engine) { - mEngine.bindNativeBufferAsFrameBuffer(buffer, this); - } - ~BindNativeBufferAsFramebuffer() { mEngine.unbindNativeBufferAsFrameBuffer(this); } - status_t getStatus() const { return mStatus; } - -protected: - friend impl::RenderEngine; - - RenderEngine& mEngine; - EGLImageKHR mImage; - uint32_t mTexName, mFbName; - status_t mStatus; -}; - -namespace impl { - -class Image; -class Surface; - -class RenderEngine : public RE::RenderEngine { - enum GlesVersion { - GLES_VERSION_1_0 = 0x10000, - GLES_VERSION_1_1 = 0x10001, - GLES_VERSION_2_0 = 0x20000, - GLES_VERSION_3_0 = 0x30000, - }; - static GlesVersion parseGlesVersion(const char* str); - - EGLDisplay mEGLDisplay; - EGLConfig mEGLConfig; - EGLContext mEGLContext; - void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt); - - static bool overrideUseContextPriorityFromConfig(bool useContextPriority); - -protected: - RenderEngine(uint32_t featureFlags); - - const uint32_t mFeatureFlags; - -public: - virtual ~RenderEngine() = 0; - - static std::unique_ptr create(int hwcFormat, uint32_t featureFlags); - - static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig); - - // RenderEngine interface implementation - - std::unique_ptr createSurface() override; - std::unique_ptr createImage() override; - - void primeCache() const override; - - // dump the extension strings. always call the base class. - void dump(String8& result) override; - - bool useNativeFenceSync() const override; - bool useWaitSync() const override; - - bool isCurrent() const; - bool setCurrentSurface(const RE::Surface& surface) override; - void resetCurrentSurface() override; - - // synchronization - - // flush submits RenderEngine command stream for execution and returns a - // native fence fd that is signaled when the execution has completed. It - // returns -1 on errors. - base::unique_fd flush() override; - // finish waits until RenderEngine command stream has been executed. It - // returns false on errors. - bool finish() override; - // waitFence inserts a wait on an external fence fd to RenderEngine - // command stream. It returns false on errors. - bool waitFence(base::unique_fd fenceFd) override; - - // helpers - void clearWithColor(float red, float green, float blue, float alpha) override; - void fillRegionWithColor(const Region& region, uint32_t height, float red, float green, - float blue, float alpha) override; - - // common to all GL versions - void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) override; - void disableScissor() override; - void genTextures(size_t count, uint32_t* names) override; - void deleteTextures(size_t count, uint32_t const* names) override; - void bindExternalTextureImage(uint32_t texName, const RE::Image& image) override; - void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) override; - - void checkErrors() const override; - - void setupColorTransform(const mat4& /* colorTransform */) override {} - - // internal to RenderEngine - EGLDisplay getEGLDisplay() const; - EGLConfig getEGLConfig() const; - - // Common implementation - bool setCurrentSurface(const RE::impl::Surface& surface); - void bindExternalTextureImage(uint32_t texName, const RE::impl::Image& image); - - void bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer, - RE::BindNativeBufferAsFramebuffer* bindHelper) override; - void unbindNativeBufferAsFrameBuffer(RE::BindNativeBufferAsFramebuffer* bindHelper) override; - - // Overriden by each specialization - virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, - uint32_t* status) = 0; - virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0; -}; - -} // namespace impl -} // namespace RE -} // namespace android - -#endif /* SF_RENDERENGINE_H_ */ diff --git a/services/surfaceflinger/RenderEngine/Surface.cpp b/services/surfaceflinger/RenderEngine/Surface.cpp index 3bf42fb8f8..3e98ab4f5e 100644 --- a/services/surfaceflinger/RenderEngine/Surface.cpp +++ b/services/surfaceflinger/RenderEngine/Surface.cpp @@ -14,11 +14,10 @@ * limitations under the License. */ -#include "Surface.h" - -#include "RenderEngine.h" +#include #include +#include #include namespace android { diff --git a/services/surfaceflinger/RenderEngine/Surface.h b/services/surfaceflinger/RenderEngine/Surface.h deleted file mode 100644 index d4d3d8c0f5..0000000000 --- a/services/surfaceflinger/RenderEngine/Surface.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 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 - -#include - -struct ANativeWindow; - -namespace android { -namespace RE { - -class Surface { -public: - virtual ~Surface() = 0; - - virtual void setCritical(bool enable) = 0; - virtual void setAsync(bool enable) = 0; - - virtual void setNativeWindow(ANativeWindow* window) = 0; - virtual void swapBuffers() const = 0; - - virtual int32_t queryRedSize() const = 0; - virtual int32_t queryGreenSize() const = 0; - virtual int32_t queryBlueSize() const = 0; - virtual int32_t queryAlphaSize() const = 0; - - virtual int32_t queryWidth() const = 0; - virtual int32_t queryHeight() const = 0; -}; - -namespace impl { - -class RenderEngine; - -class Surface final : public RE::Surface { -public: - Surface(const RenderEngine& engine); - ~Surface(); - - Surface(const Surface&) = delete; - Surface& operator=(const Surface&) = delete; - - // RE::Surface implementation - void setCritical(bool enable) override { mCritical = enable; } - void setAsync(bool enable) override { mAsync = enable; } - - void setNativeWindow(ANativeWindow* window) override; - void swapBuffers() const override; - - int32_t queryRedSize() const override; - int32_t queryGreenSize() const override; - int32_t queryBlueSize() const override; - int32_t queryAlphaSize() const override; - - int32_t queryWidth() const override; - int32_t queryHeight() const override; - -private: - EGLint queryConfig(EGLint attrib) const; - EGLint querySurface(EGLint attrib) const; - - // methods internal to RenderEngine - friend class RenderEngine; - bool getAsync() const { return mAsync; } - EGLSurface getEGLSurface() const { return mEGLSurface; } - - EGLDisplay mEGLDisplay; - EGLConfig mEGLConfig; - - bool mCritical = false; - bool mAsync = false; - - ANativeWindow* mWindow = nullptr; - EGLSurface mEGLSurface = EGL_NO_SURFACE; -}; - -} // namespace impl -} // namespace RE -} // namespace android diff --git a/services/surfaceflinger/RenderEngine/Texture.cpp b/services/surfaceflinger/RenderEngine/Texture.cpp index 351430fa06..c07ba085ee 100644 --- a/services/surfaceflinger/RenderEngine/Texture.cpp +++ b/services/surfaceflinger/RenderEngine/Texture.cpp @@ -14,9 +14,9 @@ * limitations under the License. */ -#include +#include -#include "Texture.h" +#include namespace android { diff --git a/services/surfaceflinger/RenderEngine/Texture.h b/services/surfaceflinger/RenderEngine/Texture.h deleted file mode 100644 index 56b6b31573..0000000000 --- a/services/surfaceflinger/RenderEngine/Texture.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2013 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. - */ - -#include -#include - -#ifndef SF_RENDER_ENGINE_TEXTURE_H -#define SF_RENDER_ENGINE_TEXTURE_H - -namespace android { - -class Texture { - uint32_t mTextureName; - uint32_t mTextureTarget; - size_t mWidth; - size_t mHeight; - bool mFiltering; - mat4 mTextureMatrix; - -public: - enum Target { TEXTURE_2D = 0x0DE1, TEXTURE_EXTERNAL = 0x8D65 }; - - Texture(); - Texture(Target textureTarget, uint32_t textureName); - ~Texture(); - - void init(Target textureTarget, uint32_t textureName); - - void setMatrix(float const* matrix); - void setFiltering(bool enabled); - void setDimensions(size_t width, size_t height); - - uint32_t getTextureName() const; - uint32_t getTextureTarget() const; - - const mat4& getMatrix() const; - bool getFiltering() const; - size_t getWidth() const; - size_t getHeight() const; -}; - -} /* namespace android */ -#endif /* SF_RENDER_ENGINE_TEXTURE_H */ diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/Description.h b/services/surfaceflinger/RenderEngine/include/renderengine/Description.h new file mode 100644 index 0000000000..9bc7e1c39c --- /dev/null +++ b/services/surfaceflinger/RenderEngine/include/renderengine/Description.h @@ -0,0 +1,99 @@ +/* + * Copyright 2013 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. + */ + +#include +#include + +#ifndef SF_RENDER_ENGINE_DESCRIPTION_H_ +#define SF_RENDER_ENGINE_DESCRIPTION_H_ + +namespace android { + +class Program; + +/* + * This holds the state of the rendering engine. This class is used + * to generate a corresponding GLSL program and set the appropriate + * uniform. + * + * Program and ProgramCache are friends and access the state directly + */ +class Description { +public: + Description() = default; + ~Description() = default; + + void setPremultipliedAlpha(bool premultipliedAlpha); + void setOpaque(bool opaque); + void setTexture(const Texture& texture); + void disableTexture(); + void setColor(const half4& color); + void setProjectionMatrix(const mat4& mtx); + void setColorMatrix(const mat4& mtx); + void setInputTransformMatrix(const mat3& matrix); + void setOutputTransformMatrix(const mat4& matrix); + bool hasInputTransformMatrix() const; + bool hasOutputTransformMatrix() const; + bool hasColorMatrix() const; + const mat4& getColorMatrix() const; + + void setY410BT2020(bool enable); + + enum class TransferFunction : int { + LINEAR, + SRGB, + ST2084, + HLG, // Hybrid Log-Gamma for HDR. + }; + void setInputTransferFunction(TransferFunction transferFunction); + void setOutputTransferFunction(TransferFunction transferFunction); + void setDisplayMaxLuminance(const float maxLuminance); + +private: + friend class Program; + friend class ProgramCache; + + // whether textures are premultiplied + bool mPremultipliedAlpha = false; + // whether this layer is marked as opaque + bool mOpaque = true; + + // Texture this layer uses + Texture mTexture; + bool mTextureEnabled = false; + + // color used when texturing is disabled or when setting alpha. + half4 mColor; + + // true if the sampled pixel values are in Y410/BT2020 rather than RGBA + bool mY410BT2020 = false; + + // transfer functions for the input/output + TransferFunction mInputTransferFunction = TransferFunction::LINEAR; + TransferFunction mOutputTransferFunction = TransferFunction::LINEAR; + + float mDisplayMaxLuminance; + + // projection matrix + mat4 mProjectionMatrix; + mat4 mColorMatrix; + mat3 mInputTransformMatrix; + mat4 mOutputTransformMatrix; +}; + +} /* namespace android */ + +#endif /* SF_RENDER_ENGINE_DESCRIPTION_H_ */ diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/include/renderengine/GLES20RenderEngine.h new file mode 100644 index 0000000000..0e9efdb8d5 --- /dev/null +++ b/services/surfaceflinger/RenderEngine/include/renderengine/GLES20RenderEngine.h @@ -0,0 +1,121 @@ +/* + * Copyright 2013 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. + */ + +#ifndef SF_GLES20RENDERENGINE_H_ +#define SF_GLES20RENDERENGINE_H_ + +#include +#include + +#include +#include +#include +#include + +// --------------------------------------------------------------------------- +namespace android { +// --------------------------------------------------------------------------- + +class String8; +class Mesh; +class Texture; + +namespace RE { +namespace impl { + +class GLES20RenderEngine : public RenderEngine { + GLuint mProtectedTexName; + GLint mMaxViewportDims[2]; + GLint mMaxTextureSize; + GLuint mVpWidth; + GLuint mVpHeight; + + struct Group { + GLuint texture; + GLuint fbo; + GLuint width; + GLuint height; + mat4 colorTransform; + }; + + Description mState; + Vector mGroupStack; + + virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, + uint32_t* status); + virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName); + +public: + GLES20RenderEngine(uint32_t featureFlags); // See RenderEngine::FeatureFlag + virtual ~GLES20RenderEngine(); + +protected: + virtual void dump(String8& result); + virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, + bool yswap, ui::Transform::orientation_flags rotation); + virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture, + const half4& color) override; + + // Color management related functions and state + void setSourceY410BT2020(bool enable) override; + void setSourceDataSpace(ui::Dataspace source) override; + void setOutputDataSpace(ui::Dataspace dataspace) override; + void setDisplayMaxLuminance(const float maxLuminance) override; + + virtual void setupLayerTexturing(const Texture& texture); + virtual void setupLayerBlackedOut(); + virtual void setupFillWithColor(float r, float g, float b, float a); + virtual void setupColorTransform(const mat4& colorTransform); + virtual void disableTexturing(); + virtual void disableBlending(); + + virtual void drawMesh(const Mesh& mesh); + + virtual size_t getMaxTextureSize() const; + virtual size_t getMaxViewportDims() const; + + // Current dataspace of layer being rendered + ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN; + + // Current output dataspace of the render engine + ui::Dataspace mOutputDataSpace = ui::Dataspace::UNKNOWN; + + // Whether device supports color management, currently color management + // supports sRGB, DisplayP3 color spaces. + const bool mUseColorManagement = false; + mat4 mSrgbToDisplayP3; + mat4 mDisplayP3ToSrgb; + mat3 mSrgbToXyz; + mat3 mBt2020ToXyz; + mat3 mDisplayP3ToXyz; + mat4 mXyzToSrgb; + mat4 mXyzToDisplayP3; + mat4 mXyzToBt2020; + +private: + // A data space is considered HDR data space if it has BT2020 color space + // with PQ or HLG transfer function. + bool isHdrDataSpace(const ui::Dataspace dataSpace) const; + bool needsXYZTransformMatrix() const; +}; + +// --------------------------------------------------------------------------- +} // namespace impl +} // namespace RE +} // namespace android +// --------------------------------------------------------------------------- + +#endif /* SF_GLES20RENDERENGINE_H_ */ diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/GLExtensions.h b/services/surfaceflinger/RenderEngine/include/renderengine/GLExtensions.h new file mode 100644 index 0000000000..1ff0d24a34 --- /dev/null +++ b/services/surfaceflinger/RenderEngine/include/renderengine/GLExtensions.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2010 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. + */ + +#ifndef ANDROID_SF_GLEXTENSION_H +#define ANDROID_SF_GLEXTENSION_H + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +namespace android { +// --------------------------------------------------------------------------- + +class GLExtensions : public Singleton { + friend class Singleton; + + bool mHasNoConfigContext = false; + bool mHasNativeFenceSync = false; + bool mHasFenceSync = false; + bool mHasWaitSync = false; + bool mHasProtectedContent = false; + bool mHasContextPriority = false; + + String8 mVendor; + String8 mRenderer; + String8 mVersion; + String8 mExtensions; + SortedVector mExtensionList; + + String8 mEGLVersion; + String8 mEGLExtensions; + SortedVector mEGLExtensionList; + + static SortedVector parseExtensionString(char const* extensions); + + GLExtensions(const GLExtensions&); + GLExtensions& operator=(const GLExtensions&); + +protected: + GLExtensions() = default; + +public: + bool hasNoConfigContext() const { return mHasNoConfigContext; } + bool hasNativeFenceSync() const { return mHasNativeFenceSync; } + bool hasFenceSync() const { return mHasFenceSync; } + bool hasWaitSync() const { return mHasWaitSync; } + bool hasProtectedContent() const { return mHasProtectedContent; } + bool hasContextPriority() const { return mHasContextPriority; } + + void initWithGLStrings(GLubyte const* vendor, GLubyte const* renderer, GLubyte const* version, + GLubyte const* extensions); + char const* getVendor() const; + char const* getRenderer() const; + char const* getVersion() const; + char const* getExtensions() const; + bool hasExtension(char const* extension) const; + + void initWithEGLStrings(char const* eglVersion, char const* eglExtensions); + char const* getEGLVersion() const; + char const* getEGLExtensions() const; + bool hasEGLExtension(char const* extension) const; +}; + +// --------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_SF_GLEXTENSION_H diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/Image.h b/services/surfaceflinger/RenderEngine/include/renderengine/Image.h new file mode 100644 index 0000000000..c38fe0a2ff --- /dev/null +++ b/services/surfaceflinger/RenderEngine/include/renderengine/Image.h @@ -0,0 +1,60 @@ +/* + * Copyright 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 + +#include +#include + +struct ANativeWindowBuffer; + +namespace android { +namespace RE { + +class Image { +public: + virtual ~Image() = 0; + virtual bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) = 0; +}; + +namespace impl { + +class RenderEngine; + +class Image : public RE::Image { +public: + explicit Image(const RenderEngine& engine); + ~Image() override; + + Image(const Image&) = delete; + Image& operator=(const Image&) = delete; + + bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) override; + +private: + // methods internal to RenderEngine + friend class RenderEngine; + EGLSurface getEGLImage() const { return mEGLImage; } + + EGLDisplay mEGLDisplay; + EGLImageKHR mEGLImage = EGL_NO_IMAGE_KHR; +}; + +} // namespace impl +} // namespace RE +} // namespace android diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/Mesh.h b/services/surfaceflinger/RenderEngine/include/renderengine/Mesh.h new file mode 100644 index 0000000000..d0a9ac0c65 --- /dev/null +++ b/services/surfaceflinger/RenderEngine/include/renderengine/Mesh.h @@ -0,0 +1,101 @@ +/* + * Copyright 2013 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. + */ + +#ifndef SF_RENDER_ENGINE_MESH_H +#define SF_RENDER_ENGINE_MESH_H + +#include + +namespace android { + +class Mesh { +public: + enum Primitive { + TRIANGLES = 0x0004, // GL_TRIANGLES + TRIANGLE_STRIP = 0x0005, // GL_TRIANGLE_STRIP + TRIANGLE_FAN = 0x0006 // GL_TRIANGLE_FAN + }; + + Mesh(Primitive primitive, size_t vertexCount, size_t vertexSize, size_t texCoordsSize = 0); + ~Mesh(); + + /* + * VertexArray handles the stride automatically. + */ + template + class VertexArray { + friend class Mesh; + float* mData; + size_t mStride; + VertexArray(float* data, size_t stride) : mData(data), mStride(stride) {} + + public: + TYPE& operator[](size_t index) { return *reinterpret_cast(&mData[index * mStride]); } + TYPE const& operator[](size_t index) const { + return *reinterpret_cast(&mData[index * mStride]); + } + }; + + template + VertexArray getPositionArray() { + return VertexArray(getPositions(), mStride); + } + + template + VertexArray getTexCoordArray() { + return VertexArray(getTexCoords(), mStride); + } + + Primitive getPrimitive() const; + + // returns a pointer to the vertices positions + float const* getPositions() const; + + // returns a pointer to the vertices texture coordinates + float const* getTexCoords() const; + + // number of vertices in this mesh + size_t getVertexCount() const; + + // dimension of vertices + size_t getVertexSize() const; + + // dimension of texture coordinates + size_t getTexCoordsSize() const; + + // return stride in bytes + size_t getByteStride() const; + + // return stride in floats + size_t getStride() const; + +private: + Mesh(const Mesh&); + Mesh& operator=(const Mesh&); + Mesh const& operator=(const Mesh&) const; + + float* getPositions(); + float* getTexCoords(); + float* mVertices; + size_t mVertexCount; + size_t mVertexSize; + size_t mTexCoordsSize; + size_t mStride; + Primitive mPrimitive; +}; + +} /* namespace android */ +#endif /* SF_RENDER_ENGINE_MESH_H */ diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/Program.h b/services/surfaceflinger/RenderEngine/include/renderengine/Program.h new file mode 100644 index 0000000000..5e621cbed3 --- /dev/null +++ b/services/surfaceflinger/RenderEngine/include/renderengine/Program.h @@ -0,0 +1,90 @@ +/* + * Copyright 2013 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. + */ + +#ifndef SF_RENDER_ENGINE_PROGRAM_H +#define SF_RENDER_ENGINE_PROGRAM_H + +#include + +#include +#include +#include + +namespace android { + +class String8; + +/* + * Abstracts a GLSL program comprising a vertex and fragment shader + */ +class Program { +public: + // known locations for position and texture coordinates + enum { position = 0, texCoords = 1 }; + + Program(const ProgramCache::Key& needs, const char* vertex, const char* fragment); + ~Program(); + + /* whether this object is usable */ + bool isValid() const; + + /* Binds this program to the GLES context */ + void use(); + + /* Returns the location of the specified attribute */ + GLuint getAttrib(const char* name) const; + + /* Returns the location of the specified uniform */ + GLint getUniform(const char* name) const; + + /* set-up uniforms from the description */ + void setUniforms(const Description& desc); + +private: + GLuint buildShader(const char* source, GLenum type); + String8& dumpShader(String8& result, GLenum type); + + // whether the initialization succeeded + bool mInitialized; + + // Name of the OpenGL program and shaders + GLuint mProgram; + GLuint mVertexShader; + GLuint mFragmentShader; + + /* location of the projection matrix uniform */ + GLint mProjectionMatrixLoc; + + /* location of the texture matrix uniform */ + GLint mTextureMatrixLoc; + + /* location of the sampler uniform */ + GLint mSamplerLoc; + + /* location of the color uniform */ + GLint mColorLoc; + + /* location of display luminance uniform */ + GLint mDisplayMaxLuminanceLoc; + + /* location of transform matrix */ + GLint mInputTransformMatrixLoc; + GLint mOutputTransformMatrixLoc; +}; + +} /* namespace android */ + +#endif /* SF_RENDER_ENGINE_PROGRAM_H */ diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/ProgramCache.h b/services/surfaceflinger/RenderEngine/include/renderengine/ProgramCache.h new file mode 100644 index 0000000000..a5bee45335 --- /dev/null +++ b/services/surfaceflinger/RenderEngine/include/renderengine/ProgramCache.h @@ -0,0 +1,195 @@ +/* + * Copyright 2013 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. + */ + +#ifndef SF_RENDER_ENGINE_PROGRAMCACHE_H +#define SF_RENDER_ENGINE_PROGRAMCACHE_H + +#include +#include +#include +#include +#include + +namespace android { + +class Description; +class Formatter; +class Program; +class String8; + +/* + * This class generates GLSL programs suitable to handle a given + * Description. It's responsible for figuring out what to + * generate from a Description. + * It also maintains a cache of these Programs. + */ +class ProgramCache : public Singleton { +public: + /* + * Key is used to retrieve a Program in the cache. + * A Key is generated from a Description. + */ + class Key { + friend class ProgramCache; + typedef uint32_t key_t; + key_t mKey; + + public: + enum { + BLEND_SHIFT = 0, + BLEND_MASK = 1 << BLEND_SHIFT, + BLEND_PREMULT = 1 << BLEND_SHIFT, + BLEND_NORMAL = 0 << BLEND_SHIFT, + + OPACITY_SHIFT = 1, + OPACITY_MASK = 1 << OPACITY_SHIFT, + OPACITY_OPAQUE = 1 << OPACITY_SHIFT, + OPACITY_TRANSLUCENT = 0 << OPACITY_SHIFT, + + ALPHA_SHIFT = 2, + ALPHA_MASK = 1 << ALPHA_SHIFT, + ALPHA_LT_ONE = 1 << ALPHA_SHIFT, + ALPHA_EQ_ONE = 0 << ALPHA_SHIFT, + + TEXTURE_SHIFT = 3, + TEXTURE_MASK = 3 << TEXTURE_SHIFT, + TEXTURE_OFF = 0 << TEXTURE_SHIFT, + TEXTURE_EXT = 1 << TEXTURE_SHIFT, + TEXTURE_2D = 2 << TEXTURE_SHIFT, + + INPUT_TRANSFORM_MATRIX_SHIFT = 5, + INPUT_TRANSFORM_MATRIX_MASK = 1 << INPUT_TRANSFORM_MATRIX_SHIFT, + INPUT_TRANSFORM_MATRIX_OFF = 0 << INPUT_TRANSFORM_MATRIX_SHIFT, + INPUT_TRANSFORM_MATRIX_ON = 1 << INPUT_TRANSFORM_MATRIX_SHIFT, + + OUTPUT_TRANSFORM_MATRIX_SHIFT = 6, + OUTPUT_TRANSFORM_MATRIX_MASK = 1 << OUTPUT_TRANSFORM_MATRIX_SHIFT, + OUTPUT_TRANSFORM_MATRIX_OFF = 0 << OUTPUT_TRANSFORM_MATRIX_SHIFT, + OUTPUT_TRANSFORM_MATRIX_ON = 1 << OUTPUT_TRANSFORM_MATRIX_SHIFT, + + INPUT_TF_SHIFT = 7, + INPUT_TF_MASK = 3 << INPUT_TF_SHIFT, + INPUT_TF_LINEAR = 0 << INPUT_TF_SHIFT, + INPUT_TF_SRGB = 1 << INPUT_TF_SHIFT, + INPUT_TF_ST2084 = 2 << INPUT_TF_SHIFT, + INPUT_TF_HLG = 3 << INPUT_TF_SHIFT, + + OUTPUT_TF_SHIFT = 9, + OUTPUT_TF_MASK = 3 << OUTPUT_TF_SHIFT, + OUTPUT_TF_LINEAR = 0 << OUTPUT_TF_SHIFT, + OUTPUT_TF_SRGB = 1 << OUTPUT_TF_SHIFT, + OUTPUT_TF_ST2084 = 2 << OUTPUT_TF_SHIFT, + OUTPUT_TF_HLG = 3 << OUTPUT_TF_SHIFT, + + Y410_BT2020_SHIFT = 11, + Y410_BT2020_MASK = 1 << Y410_BT2020_SHIFT, + Y410_BT2020_OFF = 0 << Y410_BT2020_SHIFT, + Y410_BT2020_ON = 1 << Y410_BT2020_SHIFT, + }; + + inline Key() : mKey(0) {} + inline Key(const Key& rhs) : mKey(rhs.mKey) {} + + inline Key& set(key_t mask, key_t value) { + mKey = (mKey & ~mask) | value; + return *this; + } + + inline bool isTexturing() const { return (mKey & TEXTURE_MASK) != TEXTURE_OFF; } + inline int getTextureTarget() const { return (mKey & TEXTURE_MASK); } + inline bool isPremultiplied() const { return (mKey & BLEND_MASK) == BLEND_PREMULT; } + inline bool isOpaque() const { return (mKey & OPACITY_MASK) == OPACITY_OPAQUE; } + inline bool hasAlpha() const { return (mKey & ALPHA_MASK) == ALPHA_LT_ONE; } + inline bool hasInputTransformMatrix() const { + return (mKey & INPUT_TRANSFORM_MATRIX_MASK) == INPUT_TRANSFORM_MATRIX_ON; + } + inline bool hasOutputTransformMatrix() const { + return (mKey & OUTPUT_TRANSFORM_MATRIX_MASK) == OUTPUT_TRANSFORM_MATRIX_ON; + } + inline bool hasTransformMatrix() const { + return hasInputTransformMatrix() || hasOutputTransformMatrix(); + } + inline int getInputTF() const { return (mKey & INPUT_TF_MASK); } + inline int getOutputTF() const { return (mKey & OUTPUT_TF_MASK); } + + // When HDR and non-HDR contents are mixed, or different types of HDR contents are + // mixed, we will do a tone mapping process to tone map the input content to output + // content. Currently, the following conversions handled, they are: + // * SDR -> HLG + // * SDR -> PQ + // * HLG -> PQ + inline bool needsToneMapping() const { + int inputTF = getInputTF(); + int outputTF = getOutputTF(); + + // Return false when converting from SDR to SDR. + if (inputTF == Key::INPUT_TF_SRGB && outputTF == Key::OUTPUT_TF_LINEAR) { + return false; + } + if (inputTF == Key::INPUT_TF_LINEAR && outputTF == Key::OUTPUT_TF_SRGB) { + return false; + } + + inputTF >>= Key::INPUT_TF_SHIFT; + outputTF >>= Key::OUTPUT_TF_SHIFT; + return inputTF != outputTF; + } + inline bool isY410BT2020() const { return (mKey & Y410_BT2020_MASK) == Y410_BT2020_ON; } + + // this is the definition of a friend function -- not a method of class Needs + friend inline int strictly_order_type(const Key& lhs, const Key& rhs) { + return (lhs.mKey < rhs.mKey) ? 1 : 0; + } + }; + + ProgramCache(); + ~ProgramCache(); + + // Generate shaders to populate the cache + void primeCache(bool useColorManagement); + + // useProgram lookup a suitable program in the cache or generates one + // if none can be found. + void useProgram(const Description& description); + +private: + // compute a cache Key from a Description + static Key computeKey(const Description& description); + // Generate EOTF based from Key. + static void generateEOTF(Formatter& fs, const Key& needs); + // Generate necessary tone mapping methods for OOTF. + static void generateToneMappingProcess(Formatter& fs, const Key& needs); + // Generate OOTF based from Key. + static void generateOOTF(Formatter& fs, const Key& needs); + // Generate OETF based from Key. + static void generateOETF(Formatter& fs, const Key& needs); + // generates a program from the Key + static Program* generateProgram(const Key& needs); + // generates the vertex shader from the Key + static String8 generateVertexShader(const Key& needs); + // generates the fragment shader from the Key + static String8 generateFragmentShader(const Key& needs); + + // Key/Value map used for caching Programs. Currently the cache + // is never shrunk. + DefaultKeyedVector mCache; +}; + +ANDROID_BASIC_TYPES_TRAITS(ProgramCache::Key) + +} /* namespace android */ + +#endif /* SF_RENDER_ENGINE_PROGRAMCACHE_H */ diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h new file mode 100644 index 0000000000..6213784f81 --- /dev/null +++ b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h @@ -0,0 +1,255 @@ +/* + * Copyright 2013 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. + */ + +#ifndef SF_RENDERENGINE_H_ +#define SF_RENDERENGINE_H_ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#define EGL_NO_CONFIG ((EGLConfig)0) + +struct ANativeWindowBuffer; + +// --------------------------------------------------------------------------- +namespace android { +// --------------------------------------------------------------------------- + +class String8; +class Rect; +class Region; +class Mesh; +class Texture; + +namespace RE { + +class Image; +class Surface; +class BindNativeBufferAsFramebuffer; + +namespace impl { +class RenderEngine; +} + +class RenderEngine { +public: + enum FeatureFlag { + USE_COLOR_MANAGEMENT = 1 << 0, // Device manages color + }; + + virtual ~RenderEngine() = 0; + + virtual std::unique_ptr createSurface() = 0; + virtual std::unique_ptr createImage() = 0; + + virtual void primeCache() const = 0; + + // dump the extension strings. always call the base class. + virtual void dump(String8& result) = 0; + + virtual bool useNativeFenceSync() const = 0; + virtual bool useWaitSync() const = 0; + + virtual bool isCurrent() const = 0; + virtual bool setCurrentSurface(const RE::Surface& surface) = 0; + virtual void resetCurrentSurface() = 0; + + // helpers + // flush submits RenderEngine command stream for execution and returns a + // native fence fd that is signaled when the execution has completed. It + // returns -1 on errors. + virtual base::unique_fd flush() = 0; + // finish waits until RenderEngine command stream has been executed. It + // returns false on errors. + virtual bool finish() = 0; + // waitFence inserts a wait on an external fence fd to RenderEngine + // command stream. It returns false on errors. + virtual bool waitFence(base::unique_fd fenceFd) = 0; + + virtual void clearWithColor(float red, float green, float blue, float alpha) = 0; + virtual void fillRegionWithColor(const Region& region, uint32_t height, float red, float green, + float blue, float alpha) = 0; + + // common to all GL versions + virtual void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) = 0; + virtual void disableScissor() = 0; + virtual void genTextures(size_t count, uint32_t* names) = 0; + virtual void deleteTextures(size_t count, uint32_t const* names) = 0; + virtual void bindExternalTextureImage(uint32_t texName, const RE::Image& image) = 0; + virtual void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) = 0; + virtual void bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer, + RE::BindNativeBufferAsFramebuffer* bindHelper) = 0; + virtual void unbindNativeBufferAsFrameBuffer(RE::BindNativeBufferAsFramebuffer* bindHelper) = 0; + + // set-up + virtual void checkErrors() const; + virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, + bool yswap, ui::Transform::orientation_flags rotation) = 0; + virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture, + const half4& color) = 0; + virtual void setupLayerTexturing(const Texture& texture) = 0; + virtual void setupLayerBlackedOut() = 0; + virtual void setupFillWithColor(float r, float g, float b, float a) = 0; + + virtual void setupColorTransform(const mat4& /* colorTransform */) = 0; + + virtual void disableTexturing() = 0; + virtual void disableBlending() = 0; + + // HDR and wide color gamut support + virtual void setSourceY410BT2020(bool enable) = 0; + virtual void setSourceDataSpace(ui::Dataspace source) = 0; + virtual void setOutputDataSpace(ui::Dataspace dataspace) = 0; + virtual void setDisplayMaxLuminance(const float maxLuminance) = 0; + + // drawing + virtual void drawMesh(const Mesh& mesh) = 0; + + // queries + virtual size_t getMaxTextureSize() const = 0; + virtual size_t getMaxViewportDims() const = 0; +}; + +class BindNativeBufferAsFramebuffer { +public: + BindNativeBufferAsFramebuffer(RenderEngine& engine, ANativeWindowBuffer* buffer) + : mEngine(engine) { + mEngine.bindNativeBufferAsFrameBuffer(buffer, this); + } + ~BindNativeBufferAsFramebuffer() { mEngine.unbindNativeBufferAsFrameBuffer(this); } + status_t getStatus() const { return mStatus; } + +protected: + friend impl::RenderEngine; + + RenderEngine& mEngine; + EGLImageKHR mImage; + uint32_t mTexName, mFbName; + status_t mStatus; +}; + +namespace impl { + +class Image; +class Surface; + +class RenderEngine : public RE::RenderEngine { + enum GlesVersion { + GLES_VERSION_1_0 = 0x10000, + GLES_VERSION_1_1 = 0x10001, + GLES_VERSION_2_0 = 0x20000, + GLES_VERSION_3_0 = 0x30000, + }; + static GlesVersion parseGlesVersion(const char* str); + + EGLDisplay mEGLDisplay; + EGLConfig mEGLConfig; + EGLContext mEGLContext; + void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt); + + static bool overrideUseContextPriorityFromConfig(bool useContextPriority); + +protected: + RenderEngine(uint32_t featureFlags); + + const uint32_t mFeatureFlags; + +public: + virtual ~RenderEngine() = 0; + + static std::unique_ptr create(int hwcFormat, uint32_t featureFlags); + + static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig); + + // RenderEngine interface implementation + + std::unique_ptr createSurface() override; + std::unique_ptr createImage() override; + + void primeCache() const override; + + // dump the extension strings. always call the base class. + void dump(String8& result) override; + + bool useNativeFenceSync() const override; + bool useWaitSync() const override; + + bool isCurrent() const; + bool setCurrentSurface(const RE::Surface& surface) override; + void resetCurrentSurface() override; + + // synchronization + + // flush submits RenderEngine command stream for execution and returns a + // native fence fd that is signaled when the execution has completed. It + // returns -1 on errors. + base::unique_fd flush() override; + // finish waits until RenderEngine command stream has been executed. It + // returns false on errors. + bool finish() override; + // waitFence inserts a wait on an external fence fd to RenderEngine + // command stream. It returns false on errors. + bool waitFence(base::unique_fd fenceFd) override; + + // helpers + void clearWithColor(float red, float green, float blue, float alpha) override; + void fillRegionWithColor(const Region& region, uint32_t height, float red, float green, + float blue, float alpha) override; + + // common to all GL versions + void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) override; + void disableScissor() override; + void genTextures(size_t count, uint32_t* names) override; + void deleteTextures(size_t count, uint32_t const* names) override; + void bindExternalTextureImage(uint32_t texName, const RE::Image& image) override; + void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) override; + + void checkErrors() const override; + + void setupColorTransform(const mat4& /* colorTransform */) override {} + + // internal to RenderEngine + EGLDisplay getEGLDisplay() const; + EGLConfig getEGLConfig() const; + + // Common implementation + bool setCurrentSurface(const RE::impl::Surface& surface); + void bindExternalTextureImage(uint32_t texName, const RE::impl::Image& image); + + void bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer, + RE::BindNativeBufferAsFramebuffer* bindHelper) override; + void unbindNativeBufferAsFrameBuffer(RE::BindNativeBufferAsFramebuffer* bindHelper) override; + + // Overriden by each specialization + virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, + uint32_t* status) = 0; + virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0; +}; + +} // namespace impl +} // namespace RE +} // namespace android + +#endif /* SF_RENDERENGINE_H_ */ diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/Surface.h b/services/surfaceflinger/RenderEngine/include/renderengine/Surface.h new file mode 100644 index 0000000000..d4d3d8c0f5 --- /dev/null +++ b/services/surfaceflinger/RenderEngine/include/renderengine/Surface.h @@ -0,0 +1,95 @@ +/* + * Copyright 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 + +#include + +struct ANativeWindow; + +namespace android { +namespace RE { + +class Surface { +public: + virtual ~Surface() = 0; + + virtual void setCritical(bool enable) = 0; + virtual void setAsync(bool enable) = 0; + + virtual void setNativeWindow(ANativeWindow* window) = 0; + virtual void swapBuffers() const = 0; + + virtual int32_t queryRedSize() const = 0; + virtual int32_t queryGreenSize() const = 0; + virtual int32_t queryBlueSize() const = 0; + virtual int32_t queryAlphaSize() const = 0; + + virtual int32_t queryWidth() const = 0; + virtual int32_t queryHeight() const = 0; +}; + +namespace impl { + +class RenderEngine; + +class Surface final : public RE::Surface { +public: + Surface(const RenderEngine& engine); + ~Surface(); + + Surface(const Surface&) = delete; + Surface& operator=(const Surface&) = delete; + + // RE::Surface implementation + void setCritical(bool enable) override { mCritical = enable; } + void setAsync(bool enable) override { mAsync = enable; } + + void setNativeWindow(ANativeWindow* window) override; + void swapBuffers() const override; + + int32_t queryRedSize() const override; + int32_t queryGreenSize() const override; + int32_t queryBlueSize() const override; + int32_t queryAlphaSize() const override; + + int32_t queryWidth() const override; + int32_t queryHeight() const override; + +private: + EGLint queryConfig(EGLint attrib) const; + EGLint querySurface(EGLint attrib) const; + + // methods internal to RenderEngine + friend class RenderEngine; + bool getAsync() const { return mAsync; } + EGLSurface getEGLSurface() const { return mEGLSurface; } + + EGLDisplay mEGLDisplay; + EGLConfig mEGLConfig; + + bool mCritical = false; + bool mAsync = false; + + ANativeWindow* mWindow = nullptr; + EGLSurface mEGLSurface = EGL_NO_SURFACE; +}; + +} // namespace impl +} // namespace RE +} // namespace android diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/Texture.h b/services/surfaceflinger/RenderEngine/include/renderengine/Texture.h new file mode 100644 index 0000000000..56b6b31573 --- /dev/null +++ b/services/surfaceflinger/RenderEngine/include/renderengine/Texture.h @@ -0,0 +1,56 @@ +/* + * Copyright 2013 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. + */ + +#include +#include + +#ifndef SF_RENDER_ENGINE_TEXTURE_H +#define SF_RENDER_ENGINE_TEXTURE_H + +namespace android { + +class Texture { + uint32_t mTextureName; + uint32_t mTextureTarget; + size_t mWidth; + size_t mHeight; + bool mFiltering; + mat4 mTextureMatrix; + +public: + enum Target { TEXTURE_2D = 0x0DE1, TEXTURE_EXTERNAL = 0x8D65 }; + + Texture(); + Texture(Target textureTarget, uint32_t textureName); + ~Texture(); + + void init(Target textureTarget, uint32_t textureName); + + void setMatrix(float const* matrix); + void setFiltering(bool enabled); + void setDimensions(size_t width, size_t height); + + uint32_t getTextureName() const; + uint32_t getTextureTarget() const; + + const mat4& getMatrix() const; + bool getFiltering() const; + size_t getWidth() const; + size_t getHeight() const; +}; + +} /* namespace android */ +#endif /* SF_RENDER_ENGINE_TEXTURE_H */ diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index dbf2f30df6..9378756ea6 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -47,7 +47,7 @@ #include #include #include - +#include #include #include #include @@ -82,7 +82,6 @@ #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/VirtualDisplaySurface.h" #include "Effects/Daltonizer.h" -#include "RenderEngine/RenderEngine.h" #include "Scheduler/DispSync.h" #include "Scheduler/DispSyncSource.h" #include "Scheduler/EventControlThread.h" diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp index 6ad1b87464..a5b522e827 100644 --- a/services/surfaceflinger/tests/fakehwc/Android.bp +++ b/services/surfaceflinger/tests/fakehwc/Android.bp @@ -30,8 +30,9 @@ cc_test { "libutils", ], static_libs: [ + "libgmock", + "librenderengine", "libtrace_proto", - "libgmock" ], header_libs: [ "android.hardware.graphics.composer@2.1-command-buffer", diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h index 36f74b6c51..b907c492a2 100644 --- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h +++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h @@ -18,11 +18,11 @@ #include -#include "RenderEngine/Image.h" -#include "RenderEngine/Mesh.h" -#include "RenderEngine/RenderEngine.h" -#include "RenderEngine/Surface.h" -#include "RenderEngine/Texture.h" +#include +#include +#include +#include +#include namespace android { namespace RE { -- cgit v1.2.3-59-g8ed1b From 10a41ffcf1465935c87266d18b279a228ab905d2 Mon Sep 17 00:00:00 2001 From: David Sodman Date: Sun, 5 Aug 2018 12:14:17 -0700 Subject: SF: Use CompositionInfo to program HWComposer Bug: 112259502 Test: cts -m CtsViewTestCases SurfaceFlinger_test vrflinger_test Change-Id: Ib0fea4e325473e552efbf4d974661d795d302244 --- services/surfaceflinger/BufferLayer.cpp | 56 ++----- services/surfaceflinger/BufferQueueLayer.cpp | 16 +- services/surfaceflinger/ColorLayer.cpp | 32 +--- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 1 - services/surfaceflinger/Layer.cpp | 82 +++------- services/surfaceflinger/LayerBE.cpp | 4 +- services/surfaceflinger/LayerBE.h | 5 +- services/surfaceflinger/SurfaceFlinger.cpp | 168 ++++++++++++++++++++- services/surfaceflinger/SurfaceFlinger.h | 6 + 9 files changed, 204 insertions(+), 166 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 44305df11e..1bb7a85628 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -242,65 +242,27 @@ void BufferLayer::setPerFrameData(const sp& display) { const auto& viewport = display->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); const auto displayId = display->getId(); - if (!hasHwcLayer(displayId)) { - ALOGE("[%s] failed to setPerFrameData: no HWC layer found (%d)", - mName.string(), displayId); - return; - } - auto& hwcInfo = getBE().mHwcLayers[displayId]; - 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(error)); - visible.dump(LOG_TAG); - } getBE().compositionInfo.hwc.visibleRegion = visible; - - 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(error)); - surfaceDamageRegion.dump(LOG_TAG); - } getBE().compositionInfo.hwc.surfaceDamage = surfaceDamageRegion; // Sideband layers if (getBE().compositionInfo.hwc.sidebandStream.get()) { setCompositionType(displayId, HWC2::Composition::Sideband); - ALOGV("[%s] Requesting Sideband composition", mName.string()); - error = hwcLayer->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle()); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(), - getBE().compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(), - static_cast(error)); - } getBE().compositionInfo.compositionType = HWC2::Composition::Sideband; return; } - // Device or Cursor layers - if (mPotentialCursor) { - ALOGV("[%s] Requesting Cursor composition", mName.string()); - setCompositionType(displayId, HWC2::Composition::Cursor); - } else { - ALOGV("[%s] Requesting Device composition", mName.string()); - setCompositionType(displayId, HWC2::Composition::Device); - } - - ALOGV("setPerFrameData: dataspace = %d", mCurrentDataSpace); - error = hwcLayer->setDataspace(mCurrentDataSpace); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace, - to_string(error).c_str(), static_cast(error)); + if (getBE().compositionInfo.hwc.skipGeometry) { + // Device or Cursor layers + if (mPotentialCursor) { + ALOGV("[%s] Requesting Cursor composition", mName.string()); + setCompositionType(displayId, HWC2::Composition::Cursor); + } else { + ALOGV("[%s] Requesting Device composition", mName.string()); + setCompositionType(displayId, HWC2::Composition::Device); + } } - const HdrMetadata& metadata = getDrawingHdrMetadata(); - error = hwcLayer->setPerFrameMetadata(display->getSupportedPerFrameMetadata(), metadata); - if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) { - ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast(error)); - } getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace; getBE().compositionInfo.hwc.hdrMetadata = getDrawingHdrMetadata(); getBE().compositionInfo.hwc.supportedPerFrameMetadata = display->getSupportedPerFrameMetadata(); diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index dc908d253c..10974b4a9d 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -337,22 +337,8 @@ status_t BufferQueueLayer::updateFrameNumber(nsecs_t latchTime) { return NO_ERROR; } -void BufferQueueLayer::setHwcLayerBuffer(const sp& display) { - const auto displayId = display->getId(); - auto& hwcInfo = getBE().mHwcLayers[displayId]; - auto& hwcLayer = hwcInfo.layer; - - uint32_t hwcSlot = 0; - sp hwcBuffer; - hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, &hwcSlot, &hwcBuffer); - +void BufferQueueLayer::setHwcLayerBuffer(const sp&) { auto acquireFence = mConsumer->getCurrentFence(); - auto error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), - getBE().compositionInfo.mBuffer->handle, to_string(error).c_str(), - static_cast(error)); - } getBE().compositionInfo.mBufferSlot = mActiveBufferSlot; getBE().compositionInfo.mBuffer = mActiveBuffer; getBE().compositionInfo.hwc.fence = acquireFence; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 24e3d94ecb..acadfa0532 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -65,48 +65,18 @@ void ColorLayer::setPerFrameData(const sp& display) { const auto& viewport = display->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); const auto displayId = display->getId(); - if (!hasHwcLayer(displayId)) { - ALOGE("[%s] failed to setPerFrameData: no HWC layer found (%d)", - mName.string(), displayId); - return; - } - auto& hwcInfo = getBE().mHwcLayers[displayId]; - 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(error)); - visible.dump(LOG_TAG); - } getBE().compositionInfo.hwc.visibleRegion = visible; + getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace; setCompositionType(displayId, HWC2::Composition::SolidColor); - - error = hwcLayer->setDataspace(mCurrentDataSpace); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace, - to_string(error).c_str(), static_cast(error)); - } getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace; half4 color = getColor(); - error = hwcLayer->setColor({static_cast(std::round(255.0f * color.r)), - static_cast(std::round(255.0f * color.g)), - static_cast(std::round(255.0f * color.b)), 255}); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set color: %s (%d)", mName.string(), to_string(error).c_str(), - static_cast(error)); - } getBE().compositionInfo.hwc.color = { static_cast(std::round(255.0f * color.r)), static_cast(std::round(255.0f * color.g)), static_cast(std::round(255.0f * color.b)), 255 }; // 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(error)); - } getBE().compositionInfo.hwc.transform = HWC2::Transform::None; } diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 873de251ed..2c94a0e04d 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -498,7 +498,6 @@ status_t HWComposer::prepare(DisplayDevice& display, validateChange(compositionInfo.compositionType, changedTypes[&*hwcLayer]); compositionInfo.compositionType = changedTypes[&*hwcLayer]; - compositionInfo.layer->mLayer->setCompositionType(displayId, compositionInfo.compositionType, false); } switch (compositionInfo.compositionType) { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 4f0b212129..58503c5341 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -494,6 +494,18 @@ void Layer::setGeometry(const sp& display, uint32_t z) { } auto& hwcInfo = getBE().mHwcLayers[displayId]; + // Device or Cursor layers + if (mPotentialCursor) { + ALOGV("[%s] Requesting Cursor composition", mName.string()); + setCompositionType(displayId, HWC2::Composition::Cursor); + } else { + ALOGV("[%s] Requesting Device composition", mName.string()); + setCompositionType(displayId, HWC2::Composition::Device); + } + + // Need to program geometry parts + getBE().compositionInfo.hwc.skipGeometry = false; + // enable this layer hwcInfo.forceClientComposition = false; @@ -501,8 +513,6 @@ void Layer::setGeometry(const sp& display, uint32_t z) { hwcInfo.forceClientComposition = true; } - auto& hwcLayer = hwcInfo.layer; - // this gives us only the "orientation" component of the transform const State& s(getDrawingState()); auto blendMode = HWC2::BlendMode::None; @@ -510,12 +520,6 @@ void Layer::setGeometry(const sp& display, uint32_t z) { 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(error)); getBE().compositionInfo.hwc.blendMode = blendMode; // apply the layer's transform, followed by the display's global transform @@ -561,39 +565,14 @@ void Layer::setGeometry(const sp& display, uint32_t z) { } const ui::Transform& tr = display->getTransform(); 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(error)); - } else { - hwcInfo.displayFrame = transformedFrame; - } getBE().compositionInfo.hwc.displayFrame = transformedFrame; FloatRect sourceCrop = computeCrop(display); - 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(error)); - } else { - hwcInfo.sourceCrop = sourceCrop; - } getBE().compositionInfo.hwc.sourceCrop = sourceCrop; float alpha = static_cast(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(error)); getBE().compositionInfo.hwc.alpha = alpha; - 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(error)); getBE().compositionInfo.hwc.z = z; int type = s.type; @@ -607,10 +586,6 @@ void Layer::setGeometry(const sp& display, uint32_t z) { } } - error = hwcLayer->setInfo(type, appId); - ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)", mName.string(), - static_cast(error)); - getBE().compositionInfo.hwc.type = type; getBE().compositionInfo.hwc.appId = appId; @@ -650,16 +625,9 @@ void Layer::setGeometry(const sp& display, uint32_t z) { if (orientation & ui::Transform::ROT_INVALID) { // we can only handle simple transformation hwcInfo.forceClientComposition = true; - getBE().mHwcLayers[displayId].compositionType = HWC2::Composition::Client; } else { auto transform = static_cast(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(error)); getBE().compositionInfo.hwc.transform = transform; } } @@ -745,28 +713,20 @@ void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green } void Layer::clearWithOpenGL(const RenderArea& renderArea) const { - clearWithOpenGL(renderArea, 0, 0, 0, 0); + getBE().compositionInfo.firstClear = true; + computeGeometry(renderArea, getBE().mMesh, false); } -void Layer::setCompositionType(int32_t displayId, HWC2::Composition type, bool callIntoHwc) { +void Layer::setCompositionType(int32_t displayId, HWC2::Composition type, bool /*callIntoHwc*/) { if (getBE().mHwcLayers.count(displayId) == 0) { ALOGE("setCompositionType called without a valid HWC layer"); return; - } - auto& hwcInfo = getBE().mHwcLayers[displayId]; - auto& hwcLayer = hwcInfo.layer; - ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", (hwcLayer)->getId(), to_string(type).c_str(), - static_cast(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(error)); + } else { + if (getBE().mHwcLayers[displayId].compositionType != type) { + ALOGV("setCompositionType: Changing compositionType from %s to %s", + to_string(getBE().mHwcLayers[displayId].compositionType).c_str(), + to_string(type).c_str()); + getBE().mHwcLayers[displayId].compositionType = type; } } } diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp index 9c6534e0d9..f389b5746e 100644 --- a/services/surfaceflinger/LayerBE.cpp +++ b/services/surfaceflinger/LayerBE.cpp @@ -43,7 +43,9 @@ LayerBE::LayerBE(const LayerBE& layer) } void LayerBE::onLayerDisplayed(const sp& releaseFence) { - mLayer->onLayerDisplayed(releaseFence); + if (mLayer) { + mLayer->onLayerDisplayed(releaseFence); + } } void LayerBE::clear(RE::RenderEngine& engine) { diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 21e7b5c9c2..531cdcd760 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -34,13 +34,14 @@ class LayerBE; struct CompositionInfo { std::string layerName; - HWC2::Composition compositionType; + HWC2::Composition compositionType = HWC2::Composition::Invalid; bool firstClear = false; sp mBuffer = nullptr; int mBufferSlot = BufferQueue::INVALID_BUFFER_SLOT; std::shared_ptr layer; struct { std::shared_ptr hwcLayer; + bool skipGeometry = true; int32_t displayId = -1; sp fence; HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid; @@ -93,8 +94,8 @@ public: void clear(RE::RenderEngine& renderEngine); Mesh& getMesh() { return mMesh; } - Layer*const mLayer; private: + Layer*const mLayer; // The mesh used to draw the layer in GLES composition mode Mesh mMesh; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e4b7cb4e03..563ca5a1c3 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1461,8 +1461,13 @@ void SurfaceFlinger::handleMessageRefresh() { preComposition(); rebuildLayerStacks(); calculateWorkingSet(); + for (const auto& [token, display] : mDisplays) { + const auto displayId = display->getId(); beginFrame(display); + for (auto& compositionInfo : getBE().mCompositionInfo[displayId]) { + setUpHWComposer(compositionInfo); + } prepareFrame(display); doDebugFlashRegions(display, repaintEverything); doComposition(display, repaintEverything); @@ -1990,6 +1995,125 @@ void SurfaceFlinger::pickColorMode(const sp& display, ColorMode* display->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent); } +void SurfaceFlinger::configureSidebandComposition(const CompositionInfo& compositionInfo) const +{ + HWC2::Error error; + LOG_ALWAYS_FATAL_IF(compositionInfo.hwc.sidebandStream == nullptr, + "CompositionType is sideband, but sideband stream is nullptr"); + error = (compositionInfo.hwc.hwcLayer) + ->setSidebandStream(compositionInfo.hwc.sidebandStream->handle()); + if (error != HWC2::Error::None) { + ALOGE("[SF] Failed to set sideband stream %p: %s (%d)", + compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(), + static_cast(error)); + } +} + +void SurfaceFlinger::configureHwcCommonData(const CompositionInfo& compositionInfo) const +{ + HWC2::Error error; + + if (!compositionInfo.hwc.skipGeometry) { + error = (compositionInfo.hwc.hwcLayer)->setBlendMode(compositionInfo.hwc.blendMode); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set blend mode %s:" + " %s (%d)", + to_string(compositionInfo.hwc.blendMode).c_str(), to_string(error).c_str(), + static_cast(error)); + + error = (compositionInfo.hwc.hwcLayer)->setDisplayFrame(compositionInfo.hwc.displayFrame); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set the display frame [%d, %d, %d, %d] %s (%d)", + compositionInfo.hwc.displayFrame.left, + compositionInfo.hwc.displayFrame.right, + compositionInfo.hwc.displayFrame.top, + compositionInfo.hwc.displayFrame.bottom, + to_string(error).c_str(), static_cast(error)); + + error = (compositionInfo.hwc.hwcLayer)->setSourceCrop(compositionInfo.hwc.sourceCrop); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: %s (%d)", + compositionInfo.hwc.sourceCrop.left, + compositionInfo.hwc.sourceCrop.right, + compositionInfo.hwc.sourceCrop.top, + compositionInfo.hwc.sourceCrop.bottom, + to_string(error).c_str(), static_cast(error)); + + error = (compositionInfo.hwc.hwcLayer)->setPlaneAlpha(compositionInfo.hwc.alpha); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set plane alpha %.3f: " + "%s (%d)", + compositionInfo.hwc.alpha, + to_string(error).c_str(), static_cast(error)); + + + error = (compositionInfo.hwc.hwcLayer)->setZOrder(compositionInfo.hwc.z); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set Z %u: %s (%d)", + compositionInfo.hwc.z, + to_string(error).c_str(), static_cast(error)); + + error = (compositionInfo.hwc.hwcLayer) + ->setInfo(compositionInfo.hwc.type, compositionInfo.hwc.appId); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set info (%d)", + static_cast(error)); + + error = (compositionInfo.hwc.hwcLayer)->setTransform(compositionInfo.hwc.transform); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set transform %s: " + "%s (%d)", + to_string(compositionInfo.hwc.transform).c_str(), to_string(error).c_str(), + static_cast(error)); + } + + error = (compositionInfo.hwc.hwcLayer)->setCompositionType(compositionInfo.compositionType); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set composition type: %s (%d)", + to_string(error).c_str(), static_cast(error)); + + error = (compositionInfo.hwc.hwcLayer)->setDataspace(compositionInfo.hwc.dataspace); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set dataspace: %s (%d)", + to_string(error).c_str(), static_cast(error)); + + error = (compositionInfo.hwc.hwcLayer)->setPerFrameMetadata( + compositionInfo.hwc.supportedPerFrameMetadata, compositionInfo.hwc.hdrMetadata); + ALOGE_IF(error != HWC2::Error::None && error != HWC2::Error::Unsupported, + "[SF] Failed to set hdrMetadata: %s (%d)", + to_string(error).c_str(), static_cast(error)); + + if (compositionInfo.compositionType == HWC2::Composition::SolidColor) { + error = (compositionInfo.hwc.hwcLayer)->setColor(compositionInfo.hwc.color); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set color: %s (%d)", + to_string(error).c_str(), static_cast(error)); + } + + error = (compositionInfo.hwc.hwcLayer)->setVisibleRegion(compositionInfo.hwc.visibleRegion); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set visible region: %s (%d)", + to_string(error).c_str(), static_cast(error)); + + error = (compositionInfo.hwc.hwcLayer)->setSurfaceDamage(compositionInfo.hwc.surfaceDamage); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set surface damage: %s (%d)", + to_string(error).c_str(), static_cast(error)); +} + +void SurfaceFlinger::configureDeviceComposition(const CompositionInfo& compositionInfo) const +{ + HWC2::Error error; + + if (compositionInfo.hwc.fence) { + error = (compositionInfo.hwc.hwcLayer)->setBuffer(compositionInfo.mBufferSlot, + compositionInfo.mBuffer, compositionInfo.hwc.fence); + ALOGE_IF(error != HWC2::Error::None, + "[SF] Failed to set buffer: %s (%d)", + to_string(error).c_str(), static_cast(error)); + } +} + void SurfaceFlinger::beginFrame(const sp& display) { bool dirty = !display->getDirtyRegion(false).isEmpty(); @@ -2035,6 +2159,33 @@ void SurfaceFlinger::prepareFrame(const sp& display) display->getId(), result, strerror(-result)); } +void SurfaceFlinger::setUpHWComposer(const CompositionInfo& compositionInfo) { + ATRACE_CALL(); + ALOGV("setUpHWComposer"); + + switch (compositionInfo.compositionType) + { + case HWC2::Composition::Invalid: + case HWC2::Composition::Client: + break; + + case HWC2::Composition::Sideband: + configureHwcCommonData(compositionInfo); + configureSidebandComposition(compositionInfo); + break; + + case HWC2::Composition::SolidColor: + configureHwcCommonData(compositionInfo); + break; + + case HWC2::Composition::Device: + case HWC2::Composition::Cursor: + configureHwcCommonData(compositionInfo); + configureDeviceComposition(compositionInfo); + break; + } +} + void SurfaceFlinger::doComposition(const sp& display, bool repaintEverything) { ATRACE_CALL(); ALOGV("doComposition"); @@ -2077,15 +2228,14 @@ void SurfaceFlinger::postFramebuffer(const sp& display) } display->onSwapBuffersCompleted(); display->makeCurrent(); - for (auto& layer : display->getVisibleLayersSortedByZ()) { + for (auto& compositionInfo : getBE().mCompositionInfo[displayId]) { sp releaseFence = Fence::NO_FENCE; - // The layer buffer from the previous frame (if any) is released // by HWC only when the release fence from this frame (if any) is // signaled. Always get the release fence from HWC first. - auto hwcLayer = layer->getHwcLayer(displayId); - if (displayId >= 0) { - releaseFence = getBE().mHwc->getLayerReleaseFence(displayId, hwcLayer); + auto hwcLayer = compositionInfo.hwc.hwcLayer; + if ((displayId >= 0) && hwcLayer) { + releaseFence = getBE().mHwc->getLayerReleaseFence(displayId, hwcLayer.get()); } // If the layer was client composited in the previous frame, we @@ -2093,12 +2243,14 @@ void SurfaceFlinger::postFramebuffer(const sp& display) // Since we do not track that, always merge with the current // client target acquire fence when it is available, even though // this is suboptimal. - if (layer->getCompositionType(displayId) == HWC2::Composition::Client) { + if (compositionInfo.compositionType == HWC2::Composition::Client) { releaseFence = Fence::merge("LayerRelease", releaseFence, display->getClientTargetAcquireFence()); } - layer->getBE().onLayerDisplayed(releaseFence); + if (compositionInfo.layer) { + compositionInfo.layer->onLayerDisplayed(releaseFence); + } } // We've got a list of layers needing fences, that are disjoint with @@ -2973,7 +3125,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& display) { opaque && (state.color.a == 1.0f) && hasClientComposition) { // never clear the very first layer since we're // guaranteed the FB is already cleared - compositionInfo.layer->mLayer->clearWithOpenGL(renderArea); + compositionInfo.layer->clear(getRenderEngine()); } break; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index ed9e212722..3dbceae89a 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -684,6 +684,7 @@ private: * to prepare the hardware composer */ void prepareFrame(const sp& display); + void setUpHWComposer(const CompositionInfo& compositionInfo); void doComposition(const sp& display, bool repainEverything); void doDebugFlashRegions(const sp& display, bool repaintEverything); void doTracing(const char* where); @@ -803,6 +804,11 @@ private: // access must be protected by mInvalidateLock volatile int32_t mRepaintEverything; + // helper methods + void configureHwcCommonData(const CompositionInfo& compositionInfo) const; + void configureDeviceComposition(const CompositionInfo& compositionInfo) const; + void configureSidebandComposition(const CompositionInfo& compositionInfo) const; + // constant members (no synchronization needed for access) nsecs_t mBootTime; bool mGpuToCpuSupported; -- cgit v1.2.3-59-g8ed1b From 833074a2eedccd6a92f38a4db6d619b7976eedf6 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Tue, 28 Aug 2018 11:53:54 -0700 Subject: [RenderEngine] Organize RenderEngine directory. This patch: 1. adds proper namespace renderengine to all RenderEngine code, and namespace gl to all GLES related code 2. creates gl/ directory for GLES backend code 3. Reorder include header files, remove unused header files. BUG: 112585051 Test: Build, flash, run display validation Change-Id: I81f0b8831213607cde08562958f7c38ddaf4c9e6 --- services/surfaceflinger/BufferLayer.cpp | 4 +- services/surfaceflinger/BufferLayer.h | 2 +- services/surfaceflinger/BufferLayerConsumer.cpp | 6 +- services/surfaceflinger/BufferLayerConsumer.h | 24 +- services/surfaceflinger/BufferStateLayer.h | 2 +- services/surfaceflinger/ColorLayer.cpp | 2 +- services/surfaceflinger/DisplayDevice.cpp | 2 +- services/surfaceflinger/DisplayDevice.h | 4 +- services/surfaceflinger/Layer.cpp | 5 +- services/surfaceflinger/Layer.h | 3 +- services/surfaceflinger/LayerBE.cpp | 6 +- services/surfaceflinger/LayerBE.h | 6 +- services/surfaceflinger/RenderEngine/Android.bp | 15 +- .../surfaceflinger/RenderEngine/Description.cpp | 7 +- .../RenderEngine/GLES20RenderEngine.cpp | 474 -------------- .../surfaceflinger/RenderEngine/GLExtensions.cpp | 124 ---- services/surfaceflinger/RenderEngine/Image.cpp | 13 +- services/surfaceflinger/RenderEngine/Mesh.cpp | 4 +- services/surfaceflinger/RenderEngine/Program.cpp | 155 ----- .../surfaceflinger/RenderEngine/ProgramCache.cpp | 688 -------------------- .../surfaceflinger/RenderEngine/RenderEngine.cpp | 58 +- services/surfaceflinger/RenderEngine/Surface.cpp | 8 +- services/surfaceflinger/RenderEngine/Texture.cpp | 6 +- .../RenderEngine/gl/GLES20RenderEngine.cpp | 468 ++++++++++++++ .../RenderEngine/gl/GLES20RenderEngine.h | 117 ++++ .../RenderEngine/gl/GLExtensions.cpp | 126 ++++ .../surfaceflinger/RenderEngine/gl/GLExtensions.h | 89 +++ .../surfaceflinger/RenderEngine/gl/Program.cpp | 159 +++++ services/surfaceflinger/RenderEngine/gl/Program.h | 95 +++ .../RenderEngine/gl/ProgramCache.cpp | 689 +++++++++++++++++++++ .../surfaceflinger/RenderEngine/gl/ProgramCache.h | 204 ++++++ .../include/renderengine/Description.h | 99 --- .../include/renderengine/GLES20RenderEngine.h | 121 ---- .../include/renderengine/GLExtensions.h | 88 --- .../RenderEngine/include/renderengine/Image.h | 10 +- .../RenderEngine/include/renderengine/Mesh.h | 4 +- .../RenderEngine/include/renderengine/Program.h | 90 --- .../include/renderengine/ProgramCache.h | 195 ------ .../include/renderengine/RenderEngine.h | 53 +- .../RenderEngine/include/renderengine/Surface.h | 12 +- .../RenderEngine/include/renderengine/Texture.h | 11 +- .../include/renderengine/private/Description.h | 103 +++ services/surfaceflinger/SurfaceFlinger.cpp | 11 +- services/surfaceflinger/SurfaceFlinger.h | 6 +- .../tests/unittests/DisplayTransactionTest.cpp | 19 +- .../tests/unittests/TestableSurfaceFlinger.h | 8 +- .../mock/RenderEngine/MockRenderEngine.cpp | 4 +- .../unittests/mock/RenderEngine/MockRenderEngine.h | 24 +- 48 files changed, 2231 insertions(+), 2192 deletions(-) delete mode 100644 services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp delete mode 100644 services/surfaceflinger/RenderEngine/GLExtensions.cpp delete mode 100644 services/surfaceflinger/RenderEngine/Program.cpp delete mode 100644 services/surfaceflinger/RenderEngine/ProgramCache.cpp create mode 100644 services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp create mode 100644 services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h create mode 100644 services/surfaceflinger/RenderEngine/gl/GLExtensions.cpp create mode 100644 services/surfaceflinger/RenderEngine/gl/GLExtensions.h create mode 100644 services/surfaceflinger/RenderEngine/gl/Program.cpp create mode 100644 services/surfaceflinger/RenderEngine/gl/Program.h create mode 100644 services/surfaceflinger/RenderEngine/gl/ProgramCache.cpp create mode 100644 services/surfaceflinger/RenderEngine/gl/ProgramCache.h delete mode 100644 services/surfaceflinger/RenderEngine/include/renderengine/Description.h delete mode 100644 services/surfaceflinger/RenderEngine/include/renderengine/GLES20RenderEngine.h delete mode 100644 services/surfaceflinger/RenderEngine/include/renderengine/GLExtensions.h delete mode 100644 services/surfaceflinger/RenderEngine/include/renderengine/Program.h delete mode 100644 services/surfaceflinger/RenderEngine/include/renderengine/ProgramCache.h create mode 100644 services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 1bb7a85628..3e2fb2e408 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -58,7 +58,7 @@ BufferLayer::BufferLayer(SurfaceFlinger* flinger, const sp& client, cons mRefreshPending(false) { ALOGV("Creating Layer %s", name.string()); - mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName); + mTexture.init(renderengine::Texture::TEXTURE_EXTERNAL, mTextureName); mPremultipliedAlpha = !(flags & ISurfaceComposerClient::eNonPremultiplied); @@ -608,7 +608,7 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT // TODO: we probably want to generate the texture coords with the mesh // here we assume that we only have 4 vertices - Mesh::VertexArray texCoords(getBE().mMesh.getTexCoordArray()); + renderengine::Mesh::VertexArray texCoords(getBE().mMesh.getTexCoordArray()); texCoords[0] = vec2(left, 1.0f - top); texCoords[1] = vec2(left, 1.0f - bottom); texCoords[2] = vec2(right, 1.0f - bottom); diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 3d06dede10..45906ff223 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -178,7 +178,7 @@ private: bool mBufferLatched; // TODO: Use mActiveBuffer? // The texture used to draw the layer in GLES composition mode - mutable Texture mTexture; + mutable renderengine::Texture mTexture; bool mRefreshPending; }; diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp index aa8f4e1dc6..fa181ad4f0 100644 --- a/services/surfaceflinger/BufferLayerConsumer.cpp +++ b/services/surfaceflinger/BufferLayerConsumer.cpp @@ -54,7 +54,8 @@ namespace android { static const mat4 mtxIdentity; BufferLayerConsumer::BufferLayerConsumer(const sp& bq, - RE::RenderEngine& engine, uint32_t tex, Layer* layer) + renderengine::RenderEngine& engine, uint32_t tex, + Layer* layer) : ConsumerBase(bq, false), mCurrentCrop(Rect::EMPTY_RECT), mCurrentTransform(0), @@ -592,7 +593,8 @@ void BufferLayerConsumer::dumpLocked(String8& result, const char* prefix) const ConsumerBase::dumpLocked(result, prefix); } -BufferLayerConsumer::Image::Image(sp graphicBuffer, RE::RenderEngine& engine) +BufferLayerConsumer::Image::Image(sp graphicBuffer, + renderengine::RenderEngine& engine) : mGraphicBuffer(graphicBuffer), mImage{engine.createImage()}, mCreated(false), diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h index 943b8a8103..257a4e5be1 100644 --- a/services/surfaceflinger/BufferLayerConsumer.h +++ b/services/surfaceflinger/BufferLayerConsumer.h @@ -37,10 +37,10 @@ class DispSync; class Layer; class String8; -namespace RE { +namespace renderengine { class RenderEngine; class Image; -} // namespace RE +} // namespace renderengine /* * BufferLayerConsumer consumes buffers of graphics data from a BufferQueue, @@ -73,7 +73,7 @@ public: // BufferLayerConsumer constructs a new BufferLayerConsumer object. The // tex parameter indicates the name of the RenderEngine texture to which // images are to be streamed. - BufferLayerConsumer(const sp& bq, RE::RenderEngine& engine, + BufferLayerConsumer(const sp& bq, renderengine::RenderEngine& engine, uint32_t tex, Layer* layer); // Sets the contents changed listener. This should be used instead of @@ -216,19 +216,19 @@ protected: status_t bindTextureImageLocked(); private: - // Image is a utility class for tracking and creating RE::Images. There + // Image is a utility class for tracking and creating renderengine::Images. There // is primarily just one image per slot, but there is also special cases: // - After freeBuffer, we must still keep the current image/buffer - // Reference counting RE::Images lets us handle all these cases easily while - // also only creating new RE::Images from buffers when required. + // Reference counting renderengine::Images lets us handle all these cases easily while + // also only creating new renderengine::Images from buffers when required. class Image : public LightRefBase { public: - Image(sp graphicBuffer, RE::RenderEngine& engine); + Image(sp graphicBuffer, renderengine::RenderEngine& engine); Image(const Image& rhs) = delete; Image& operator=(const Image& rhs) = delete; - // createIfNeeded creates an RE::Image if we haven't created one yet. + // createIfNeeded creates an renderengine::Image if we haven't created one yet. status_t createIfNeeded(); const sp& graphicBuffer() { return mGraphicBuffer; } @@ -236,7 +236,7 @@ private: return mGraphicBuffer == nullptr ? nullptr : mGraphicBuffer->handle; } - const RE::Image& image() const { return *mImage; } + const renderengine::Image& image() const { return *mImage; } private: // Only allow instantiation using ref counting. @@ -247,7 +247,7 @@ private: sp mGraphicBuffer; // mImage is the image created from mGraphicBuffer. - std::unique_ptr mImage; + std::unique_ptr mImage; bool mCreated; int32_t mCropWidth; int32_t mCropHeight; @@ -255,7 +255,7 @@ private: // freeBufferLocked frees up the given buffer slot. If the slot has been // initialized this will release the reference to the GraphicBuffer in - // that slot and destroy the RE::Image in that slot. Otherwise it has no + // that slot and destroy the renderengine::Image in that slot. Otherwise it has no // effect. // // This method must be called with mMutex locked. @@ -351,7 +351,7 @@ private: // setFilteringEnabled(). bool mFilteringEnabled; - RE::RenderEngine& mRE; + renderengine::RenderEngine& mRE; // mTexName is the name of the RenderEngine texture to which streamed // images will be bound when bindTexImage is called. It is set at diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 038eb01209..5cc8d567b9 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -127,7 +127,7 @@ private: private: void onFirstRef() override; - std::unique_ptr mTextureImage; + std::unique_ptr mTextureImage; std::array mTransformMatrix; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index acadfa0532..9bf75e83d2 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -45,7 +45,7 @@ void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */, bool useIdentityTransform) { half4 color = getColor(); if (color.a > 0) { - Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2); + renderengine::Mesh mesh(renderengine::Mesh::TRIANGLE_FAN, 4, 2); computeGeometry(renderArea, mesh, useIdentityTransform); auto& engine(mFlinger->getRenderEngine()); engine.setupLayerBlending(getPremultipledAlpha(), false /* opaque */, diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index aab6c22819..1a997185a2 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -215,7 +215,7 @@ DisplayDevice::DisplayDevice( const wp& displayToken, const sp& nativeWindow, const sp& displaySurface, - std::unique_ptr renderSurface, + std::unique_ptr renderSurface, int displayWidth, int displayHeight, bool hasWideColorGamut, diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index ddb09c5086..912deef160 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -84,7 +84,7 @@ public: const wp& displayToken, const sp& nativeWindow, const sp& displaySurface, - std::unique_ptr renderSurface, + std::unique_ptr renderSurface, int displayWidth, int displayHeight, bool hasWideColorGamut, @@ -231,7 +231,7 @@ private: sp mNativeWindow; sp mDisplaySurface; - std::unique_ptr mSurface; + std::unique_ptr mSurface; int mDisplayWidth; int mDisplayHeight; mutable uint32_t mPageFlipCount; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index c7d67e2298..d2ab1b3d48 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -795,7 +795,8 @@ static void boundPoint(vec2* point, const Rect& crop) { } } -void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh, +void Layer::computeGeometry(const RenderArea& renderArea, + renderengine::Mesh& mesh, bool useIdentityTransform) const { const Layer::State& s(getDrawingState()); const ui::Transform renderAreaTransform(renderArea.getTransform()); @@ -823,7 +824,7 @@ void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh, boundPoint(&rt, finalCrop); } - Mesh::VertexArray position(mesh.getPositionArray()); + renderengine::Mesh::VertexArray position(mesh.getPositionArray()); position[0] = renderAreaTransform.transform(lt); position[1] = renderAreaTransform.transform(lb); position[2] = renderAreaTransform.transform(rb); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 604ec656fc..56261b9268 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -284,7 +284,8 @@ public: return getLayerStack() == layerStack && (!mPrimaryDisplayOnly || isPrimaryDisplay); } - void computeGeometry(const RenderArea& renderArea, Mesh& mesh, bool useIdentityTransform) const; + void computeGeometry(const RenderArea& renderArea, renderengine::Mesh& mesh, + bool useIdentityTransform) const; FloatRect computeBounds(const Region& activeTransparentRegion) const; FloatRect computeBounds() const; diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp index f389b5746e..da98bf5ee2 100644 --- a/services/surfaceflinger/LayerBE.cpp +++ b/services/surfaceflinger/LayerBE.cpp @@ -30,14 +30,14 @@ namespace android { LayerBE::LayerBE(Layer* layer, std::string layerName) : mLayer(layer), - mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) { + mMesh(renderengine::Mesh::TRIANGLE_FAN, 4, 2, 2) { compositionInfo.layer = std::make_shared(*this); compositionInfo.layerName = layerName; } LayerBE::LayerBE(const LayerBE& layer) : mLayer(layer.mLayer), - mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) { + mMesh(renderengine::Mesh::TRIANGLE_FAN, 4, 2, 2) { compositionInfo.layer = layer.compositionInfo.layer; compositionInfo.layerName = layer.mLayer->getName().string(); } @@ -48,7 +48,7 @@ void LayerBE::onLayerDisplayed(const sp& releaseFence) { } } -void LayerBE::clear(RE::RenderEngine& engine) { +void LayerBE::clear(renderengine::RenderEngine& engine) { engine.setupFillWithColor(0, 0, 0, 0); engine.drawMesh(mMesh); } diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 531cdcd760..f5150a7feb 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -91,13 +91,13 @@ public: explicit LayerBE(const LayerBE& layer); void onLayerDisplayed(const sp& releaseFence); - void clear(RE::RenderEngine& renderEngine); - Mesh& getMesh() { return mMesh; } + void clear(renderengine::RenderEngine& renderEngine); + renderengine::Mesh& getMesh() { return mMesh; } private: Layer*const mLayer; // The mesh used to draw the layer in GLES composition mode - Mesh mMesh; + renderengine::Mesh mMesh; // HWC items, accessed from the main thread struct HWCInfo { diff --git a/services/surfaceflinger/RenderEngine/Android.bp b/services/surfaceflinger/RenderEngine/Android.bp index 13752f21d4..f62596fb6e 100644 --- a/services/surfaceflinger/RenderEngine/Android.bp +++ b/services/surfaceflinger/RenderEngine/Android.bp @@ -41,18 +41,24 @@ filegroup { name: "librenderengine_sources", srcs: [ "Description.cpp", - "GLES20RenderEngine.cpp", - "GLExtensions.cpp", "Image.cpp", "Mesh.cpp", - "Program.cpp", - "ProgramCache.cpp", "RenderEngine.cpp", "Surface.cpp", "Texture.cpp", ], } +filegroup { + name: "librenderengine_gl_sources", + srcs: [ + "gl/GLES20RenderEngine.cpp", + "gl/GLExtensions.cpp", + "gl/Program.cpp", + "gl/ProgramCache.cpp", + ], +} + cc_library_static { name: "librenderengine", defaults: ["librenderengine_defaults"], @@ -68,6 +74,7 @@ cc_library_static { ], srcs: [ ":librenderengine_sources", + ":librenderengine_gl_sources", ], lto: { thin: true, diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp index d5f2103537..b7522da9c6 100644 --- a/services/surfaceflinger/RenderEngine/Description.cpp +++ b/services/surfaceflinger/RenderEngine/Description.cpp @@ -14,14 +14,14 @@ * limitations under the License. */ -#include +#include #include -#include #include namespace android { +namespace renderengine { void Description::setPremultipliedAlpha(bool premultipliedAlpha) { mPremultipliedAlpha = premultipliedAlpha; @@ -95,4 +95,5 @@ void Description::setDisplayMaxLuminance(const float maxLuminance) { mDisplayMaxLuminance = maxLuminance; } -} /* namespace android */ +} // namespace renderengine +} // namespace android diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp deleted file mode 100644 index 617ba76197..0000000000 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ /dev/null @@ -1,474 +0,0 @@ -/* - * Copyright 2013 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 "RenderEngine" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -// --------------------------------------------------------------------------- -bool checkGlError(const char* op, int lineNumber) { - bool errorFound = false; - GLint error = glGetError(); - while (error != GL_NO_ERROR) { - errorFound = true; - error = glGetError(); - ALOGV("after %s() (line # %d) glError (0x%x)\n", op, lineNumber, error); - } - return errorFound; -} - -static constexpr bool outputDebugPPMs = false; - -void writePPM(const char* basename, GLuint width, GLuint height) { - ALOGV("writePPM #%s: %d x %d", basename, width, height); - - std::vector pixels(width * height * 4); - std::vector outBuffer(width * height * 3); - - // TODO(courtneygo): We can now have float formats, need - // to remove this code or update to support. - // Make returned pixels fit in uint32_t, one byte per component - glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); - if (checkGlError(__FUNCTION__, __LINE__)) { - return; - } - - std::string filename(basename); - filename.append(".ppm"); - std::ofstream file(filename.c_str(), std::ios::binary); - if (!file.is_open()) { - ALOGE("Unable to open file: %s", filename.c_str()); - ALOGE("You may need to do: \"adb shell setenforce 0\" to enable " - "surfaceflinger to write debug images"); - return; - } - - file << "P6\n"; - file << width << "\n"; - file << height << "\n"; - file << 255 << "\n"; - - auto ptr = reinterpret_cast(pixels.data()); - auto outPtr = reinterpret_cast(outBuffer.data()); - for (int y = height - 1; y >= 0; y--) { - char* data = ptr + y * width * sizeof(uint32_t); - - for (GLuint x = 0; x < width; x++) { - // Only copy R, G and B components - outPtr[0] = data[0]; - outPtr[1] = data[1]; - outPtr[2] = data[2]; - data += sizeof(uint32_t); - outPtr += 3; - } - } - file.write(reinterpret_cast(outBuffer.data()), outBuffer.size()); -} - -// --------------------------------------------------------------------------- -namespace android { -namespace RE { -namespace impl { -// --------------------------------------------------------------------------- - -using ui::Dataspace; - -GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags) - : RenderEngine(featureFlags), - mVpWidth(0), - mVpHeight(0), - mUseColorManagement(featureFlags & USE_COLOR_MANAGEMENT) { - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); - glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims); - - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glPixelStorei(GL_PACK_ALIGNMENT, 4); - - const uint16_t protTexData[] = {0}; - glGenTextures(1, &mProtectedTexName); - glBindTexture(GL_TEXTURE_2D, mProtectedTexName); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData); - - // mColorBlindnessCorrection = M; - - if (mUseColorManagement) { - ColorSpace srgb(ColorSpace::sRGB()); - ColorSpace displayP3(ColorSpace::DisplayP3()); - ColorSpace bt2020(ColorSpace::BT2020()); - - // Compute sRGB to Display P3 transform matrix. - // NOTE: For now, we are limiting output wide color space support to - // Display-P3 only. - mSrgbToDisplayP3 = mat4(ColorSpaceConnector(srgb, displayP3).getTransform()); - - // Compute Display P3 to sRGB transform matrix. - mDisplayP3ToSrgb = mat4(ColorSpaceConnector(displayP3, srgb).getTransform()); - - // no chromatic adaptation needed since all color spaces use D65 for their white points. - mSrgbToXyz = srgb.getRGBtoXYZ(); - mDisplayP3ToXyz = displayP3.getRGBtoXYZ(); - mBt2020ToXyz = bt2020.getRGBtoXYZ(); - mXyzToSrgb = mat4(srgb.getXYZtoRGB()); - mXyzToDisplayP3 = mat4(displayP3.getXYZtoRGB()); - mXyzToBt2020 = mat4(bt2020.getXYZtoRGB()); - } -} - -GLES20RenderEngine::~GLES20RenderEngine() {} - -size_t GLES20RenderEngine::getMaxTextureSize() const { - return mMaxTextureSize; -} - -size_t GLES20RenderEngine::getMaxViewportDims() const { - return mMaxViewportDims[0] < mMaxViewportDims[1] ? mMaxViewportDims[0] : mMaxViewportDims[1]; -} - -void GLES20RenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, - size_t hwh, bool yswap, - ui::Transform::orientation_flags rotation) { - int32_t l = sourceCrop.left; - int32_t r = sourceCrop.right; - - // In GL, (0, 0) is the bottom-left corner, so flip y coordinates - int32_t t = hwh - sourceCrop.top; - int32_t b = hwh - sourceCrop.bottom; - - mat4 m; - if (yswap) { - m = mat4::ortho(l, r, t, b, 0, 1); - } else { - m = mat4::ortho(l, r, b, t, 0, 1); - } - - // Apply custom rotation to the projection. - float rot90InRadians = 2.0f * static_cast(M_PI) / 4.0f; - switch (rotation) { - case ui::Transform::ROT_0: - break; - case ui::Transform::ROT_90: - m = mat4::rotate(rot90InRadians, vec3(0, 0, 1)) * m; - break; - case ui::Transform::ROT_180: - m = mat4::rotate(rot90InRadians * 2.0f, vec3(0, 0, 1)) * m; - break; - case ui::Transform::ROT_270: - m = mat4::rotate(rot90InRadians * 3.0f, vec3(0, 0, 1)) * m; - break; - default: - break; - } - - glViewport(0, 0, vpw, vph); - mState.setProjectionMatrix(m); - mVpWidth = vpw; - mVpHeight = vph; -} - -void GLES20RenderEngine::setupLayerBlending(bool premultipliedAlpha, bool opaque, - bool disableTexture, const half4& color) { - mState.setPremultipliedAlpha(premultipliedAlpha); - mState.setOpaque(opaque); - mState.setColor(color); - - if (disableTexture) { - mState.disableTexture(); - } - - if (color.a < 1.0f || !opaque) { - glEnable(GL_BLEND); - glBlendFunc(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } else { - glDisable(GL_BLEND); - } -} - -void GLES20RenderEngine::setSourceY410BT2020(bool enable) { - mState.setY410BT2020(enable); -} - -void GLES20RenderEngine::setSourceDataSpace(Dataspace source) { - mDataSpace = source; -} - -void GLES20RenderEngine::setOutputDataSpace(Dataspace dataspace) { - mOutputDataSpace = dataspace; -} - -void GLES20RenderEngine::setDisplayMaxLuminance(const float maxLuminance) { - mState.setDisplayMaxLuminance(maxLuminance); -} - -void GLES20RenderEngine::setupLayerTexturing(const Texture& texture) { - GLuint target = texture.getTextureTarget(); - glBindTexture(target, texture.getTextureName()); - GLenum filter = GL_NEAREST; - if (texture.getFiltering()) { - filter = GL_LINEAR; - } - glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter); - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter); - - mState.setTexture(texture); -} - -void GLES20RenderEngine::setupLayerBlackedOut() { - glBindTexture(GL_TEXTURE_2D, mProtectedTexName); - Texture texture(Texture::TEXTURE_2D, mProtectedTexName); - texture.setDimensions(1, 1); // FIXME: we should get that from somewhere - mState.setTexture(texture); -} - -void GLES20RenderEngine::setupColorTransform(const mat4& colorTransform) { - mState.setColorMatrix(colorTransform); -} - -void GLES20RenderEngine::disableTexturing() { - mState.disableTexture(); -} - -void GLES20RenderEngine::disableBlending() { - glDisable(GL_BLEND); -} - -void GLES20RenderEngine::bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, - uint32_t* fbName, uint32_t* status) { - GLuint tname, name; - // turn our EGLImage into a texture - glGenTextures(1, &tname); - glBindTexture(GL_TEXTURE_2D, tname); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); - - // create a Framebuffer Object to render into - glGenFramebuffers(1, &name); - glBindFramebuffer(GL_FRAMEBUFFER, name); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0); - - *status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - *texName = tname; - *fbName = name; -} - -void GLES20RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName) { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &fbName); - glDeleteTextures(1, &texName); -} - -void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) { - mState.setPremultipliedAlpha(true); - mState.setOpaque(false); - mState.setColor(half4(r, g, b, a)); - mState.disableTexture(); - glDisable(GL_BLEND); -} - -void GLES20RenderEngine::drawMesh(const Mesh& mesh) { - ATRACE_CALL(); - if (mesh.getTexCoordsSize()) { - glEnableVertexAttribArray(Program::texCoords); - glVertexAttribPointer(Program::texCoords, mesh.getTexCoordsSize(), GL_FLOAT, GL_FALSE, - mesh.getByteStride(), mesh.getTexCoords()); - } - - glVertexAttribPointer(Program::position, mesh.getVertexSize(), GL_FLOAT, GL_FALSE, - mesh.getByteStride(), mesh.getPositions()); - - // By default, DISPLAY_P3 is the only supported wide color output. However, - // when HDR content is present, hardware composer may be able to handle - // BT2020 data space, in that case, the output data space is set to be - // BT2020_HLG or BT2020_PQ respectively. In GPU fall back we need - // to respect this and convert non-HDR content to HDR format. - if (mUseColorManagement) { - Description managedState = mState; - Dataspace inputStandard = static_cast(mDataSpace & Dataspace::STANDARD_MASK); - Dataspace inputTransfer = static_cast(mDataSpace & Dataspace::TRANSFER_MASK); - Dataspace outputStandard = static_cast(mOutputDataSpace & - Dataspace::STANDARD_MASK); - Dataspace outputTransfer = static_cast(mOutputDataSpace & - Dataspace::TRANSFER_MASK); - bool needsXYZConversion = needsXYZTransformMatrix(); - - if (needsXYZConversion) { - // The supported input color spaces are standard RGB, Display P3 and BT2020. - switch (inputStandard) { - case Dataspace::STANDARD_DCI_P3: - managedState.setInputTransformMatrix(mDisplayP3ToXyz); - break; - case Dataspace::STANDARD_BT2020: - managedState.setInputTransformMatrix(mBt2020ToXyz); - break; - default: - managedState.setInputTransformMatrix(mSrgbToXyz); - break; - } - - // The supported output color spaces are BT2020, Display P3 and standard RGB. - switch (outputStandard) { - case Dataspace::STANDARD_BT2020: - managedState.setOutputTransformMatrix(mXyzToBt2020); - break; - case Dataspace::STANDARD_DCI_P3: - managedState.setOutputTransformMatrix(mXyzToDisplayP3); - break; - default: - managedState.setOutputTransformMatrix(mXyzToSrgb); - break; - } - } else if (inputStandard != outputStandard) { - // At this point, the input data space and output data space could be both - // HDR data spaces, but they match each other, we do nothing in this case. - // In addition to the case above, the input data space could be - // - scRGB linear - // - scRGB non-linear - // - sRGB - // - Display P3 - // The output data spaces could be - // - sRGB - // - Display P3 - if (outputStandard == Dataspace::STANDARD_BT709) { - managedState.setOutputTransformMatrix(mDisplayP3ToSrgb); - } else if (outputStandard == Dataspace::STANDARD_DCI_P3) { - managedState.setOutputTransformMatrix(mSrgbToDisplayP3); - } - } - - // we need to convert the RGB value to linear space and convert it back when: - // - there is a color matrix that is not an identity matrix, or - // - there is an output transform matrix that is not an identity matrix, or - // - the input transfer function doesn't match the output transfer function. - if (managedState.hasColorMatrix() || managedState.hasOutputTransformMatrix() || - inputTransfer != outputTransfer) { - switch (inputTransfer) { - case Dataspace::TRANSFER_ST2084: - managedState.setInputTransferFunction(Description::TransferFunction::ST2084); - break; - case Dataspace::TRANSFER_HLG: - managedState.setInputTransferFunction(Description::TransferFunction::HLG); - break; - case Dataspace::TRANSFER_LINEAR: - managedState.setInputTransferFunction(Description::TransferFunction::LINEAR); - break; - default: - managedState.setInputTransferFunction(Description::TransferFunction::SRGB); - break; - } - - switch (outputTransfer) { - case Dataspace::TRANSFER_ST2084: - managedState.setOutputTransferFunction(Description::TransferFunction::ST2084); - break; - case Dataspace::TRANSFER_HLG: - managedState.setOutputTransferFunction(Description::TransferFunction::HLG); - break; - default: - managedState.setOutputTransferFunction(Description::TransferFunction::SRGB); - break; - } - } - - ProgramCache::getInstance().useProgram(managedState); - - glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount()); - - if (outputDebugPPMs) { - static uint64_t managedColorFrameCount = 0; - std::ostringstream out; - out << "/data/texture_out" << managedColorFrameCount++; - writePPM(out.str().c_str(), mVpWidth, mVpHeight); - } - } else { - ProgramCache::getInstance().useProgram(mState); - - glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount()); - } - - if (mesh.getTexCoordsSize()) { - glDisableVertexAttribArray(Program::texCoords); - } -} - -void GLES20RenderEngine::dump(String8& result) { - RenderEngine::dump(result); - result.appendFormat("RenderEngine last dataspace conversion: (%s) to (%s)\n", - dataspaceDetails(static_cast(mDataSpace)).c_str(), - dataspaceDetails(static_cast(mOutputDataSpace)).c_str()); -} - -bool GLES20RenderEngine::isHdrDataSpace(const Dataspace dataSpace) const { - const Dataspace standard = static_cast(dataSpace & Dataspace::STANDARD_MASK); - const Dataspace transfer = static_cast(dataSpace & Dataspace::TRANSFER_MASK); - return standard == Dataspace::STANDARD_BT2020 && - (transfer == Dataspace::TRANSFER_ST2084 || transfer == Dataspace::TRANSFER_HLG); -} - -// For convenience, we want to convert the input color space to XYZ color space first, -// and then convert from XYZ color space to output color space when -// - SDR and HDR contents are mixed, either SDR content will be converted to HDR or -// HDR content will be tone-mapped to SDR; Or, -// - there are HDR PQ and HLG contents presented at the same time, where we want to convert -// HLG content to PQ content. -// In either case above, we need to operate the Y value in XYZ color space. Thus, when either -// input data space or output data space is HDR data space, and the input transfer function -// doesn't match the output transfer function, we would enable an intermediate transfrom to -// XYZ color space. -bool GLES20RenderEngine::needsXYZTransformMatrix() const { - const bool isInputHdrDataSpace = isHdrDataSpace(mDataSpace); - const bool isOutputHdrDataSpace = isHdrDataSpace(mOutputDataSpace); - const Dataspace inputTransfer = static_cast(mDataSpace & Dataspace::TRANSFER_MASK); - const Dataspace outputTransfer = static_cast(mOutputDataSpace & - Dataspace::TRANSFER_MASK); - - return (isInputHdrDataSpace || isOutputHdrDataSpace) && inputTransfer != outputTransfer; -} - -// --------------------------------------------------------------------------- -} // namespace impl -} // namespace RE -} // namespace android -// --------------------------------------------------------------------------- - -#if defined(__gl_h_) -#error "don't include gl/gl.h in this file" -#endif diff --git a/services/surfaceflinger/RenderEngine/GLExtensions.cpp b/services/surfaceflinger/RenderEngine/GLExtensions.cpp deleted file mode 100644 index b4fb2a1c55..0000000000 --- a/services/surfaceflinger/RenderEngine/GLExtensions.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2010 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. - */ - -#include - -#include -#include -#include - -namespace android { -// --------------------------------------------------------------------------- - -ANDROID_SINGLETON_STATIC_INSTANCE(GLExtensions) - -SortedVector GLExtensions::parseExtensionString(char const* extensions) { - SortedVector list; - - char const* curr = extensions; - char const* head = curr; - do { - head = strchr(curr, ' '); - String8 s(curr, head ? head - curr : strlen(curr)); - if (s.length()) { - list.add(s); - } - curr = head + 1; - } while (head); - - return list; -} - -void GLExtensions::initWithGLStrings(GLubyte const* vendor, GLubyte const* renderer, - GLubyte const* version, GLubyte const* extensions) { - mVendor = (char const*)vendor; - mRenderer = (char const*)renderer; - mVersion = (char const*)version; - mExtensions = (char const*)extensions; - mExtensionList = parseExtensionString(mExtensions); -} - -bool GLExtensions::hasExtension(char const* extension) const { - const String8 s(extension); - return mExtensionList.indexOf(s) >= 0; -} - -char const* GLExtensions::getVendor() const { - return mVendor.string(); -} - -char const* GLExtensions::getRenderer() const { - return mRenderer.string(); -} - -char const* GLExtensions::getVersion() const { - return mVersion.string(); -} - -char const* GLExtensions::getExtensions() const { - return mExtensions.string(); -} - -void GLExtensions::initWithEGLStrings(char const* eglVersion, char const* eglExtensions) { - mEGLVersion = eglVersion; - mEGLExtensions = eglExtensions; - mEGLExtensionList = parseExtensionString(mEGLExtensions); - - // EGL_ANDROIDX_no_config_context is an experimental extension with no - // written specification. It will be replaced by something more formal. - // SurfaceFlinger is using it to allow a single EGLContext to render to - // both a 16-bit primary display framebuffer and a 32-bit virtual display - // framebuffer. - // - // EGL_KHR_no_config_context is official extension to allow creating a - // context that works with any surface of a display. - if (hasEGLExtension("EGL_ANDROIDX_no_config_context") || - hasEGLExtension("EGL_KHR_no_config_context")) { - mHasNoConfigContext = true; - } - - if (hasEGLExtension("EGL_ANDROID_native_fence_sync")) { - mHasNativeFenceSync = true; - } - if (hasEGLExtension("EGL_KHR_fence_sync")) { - mHasFenceSync = true; - } - if (hasEGLExtension("EGL_KHR_wait_sync")) { - mHasWaitSync = true; - } - if (hasEGLExtension("EGL_EXT_protected_content")) { - mHasProtectedContent = true; - } - if (hasEGLExtension("EGL_IMG_context_priority")) { - mHasContextPriority = true; - } -} - -char const* GLExtensions::getEGLVersion() const { - return mEGLVersion.string(); -} - -char const* GLExtensions::getEGLExtensions() const { - return mEGLExtensions.string(); -} - -bool GLExtensions::hasEGLExtension(char const* extension) const { - const String8 s(extension); - return mEGLExtensionList.indexOf(s) >= 0; -} - -// --------------------------------------------------------------------------- -}; // namespace android diff --git a/services/surfaceflinger/RenderEngine/Image.cpp b/services/surfaceflinger/RenderEngine/Image.cpp index ee140eb000..cabcace672 100644 --- a/services/surfaceflinger/RenderEngine/Image.cpp +++ b/services/surfaceflinger/RenderEngine/Image.cpp @@ -19,12 +19,11 @@ #include #include - -#include #include +#include "gl/GLExtensions.h" namespace android { -namespace RE { +namespace renderengine { Image::~Image() = default; @@ -43,7 +42,7 @@ static std::vector buildAttributeList(bool isProtected) { attrs.push_back(EGL_IMAGE_PRESERVED_KHR); attrs.push_back(EGL_TRUE); - if (isProtected && GLExtensions::getInstance().hasProtectedContent()) { + if (isProtected && gl::GLExtensions::getInstance().hasProtectedContent()) { attrs.push_back(EGL_PROTECTED_CONTENT_EXT); attrs.push_back(EGL_TRUE); } @@ -74,6 +73,6 @@ bool Image::setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) return true; } -} // namespace impl -} // namespace RE -} // namespace android +} // namespace impl +} // namespace renderengine +} // namespace android diff --git a/services/surfaceflinger/RenderEngine/Mesh.cpp b/services/surfaceflinger/RenderEngine/Mesh.cpp index 43852eba33..5a3c2c85b0 100644 --- a/services/surfaceflinger/RenderEngine/Mesh.cpp +++ b/services/surfaceflinger/RenderEngine/Mesh.cpp @@ -19,6 +19,7 @@ #include namespace android { +namespace renderengine { Mesh::Mesh(Primitive primitive, size_t vertexCount, size_t vertexSize, size_t texCoordSize) : mVertexCount(vertexCount), @@ -94,4 +95,5 @@ size_t Mesh::getStride() const { return mStride; } -} /* namespace android */ +} // namespace renderengine +} // namespace android diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/Program.cpp deleted file mode 100644 index 87371dc7e7..0000000000 --- a/services/surfaceflinger/RenderEngine/Program.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/*Gluint - * Copyright 2013 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. - */ - -#include - -#include - -#include -#include -#include -#include -#include - -namespace android { - -Program::Program(const ProgramCache::Key& /*needs*/, const char* vertex, const char* fragment) - : mInitialized(false) { - GLuint vertexId = buildShader(vertex, GL_VERTEX_SHADER); - GLuint fragmentId = buildShader(fragment, GL_FRAGMENT_SHADER); - GLuint programId = glCreateProgram(); - glAttachShader(programId, vertexId); - glAttachShader(programId, fragmentId); - glBindAttribLocation(programId, position, "position"); - glBindAttribLocation(programId, texCoords, "texCoords"); - glLinkProgram(programId); - - GLint status; - glGetProgramiv(programId, GL_LINK_STATUS, &status); - if (status != GL_TRUE) { - ALOGE("Error while linking shaders:"); - GLint infoLen = 0; - glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &infoLen); - if (infoLen > 1) { - GLchar log[infoLen]; - glGetProgramInfoLog(programId, infoLen, 0, &log[0]); - ALOGE("%s", log); - } - glDetachShader(programId, vertexId); - glDetachShader(programId, fragmentId); - glDeleteShader(vertexId); - glDeleteShader(fragmentId); - glDeleteProgram(programId); - } else { - mProgram = programId; - mVertexShader = vertexId; - mFragmentShader = fragmentId; - mInitialized = true; - mProjectionMatrixLoc = glGetUniformLocation(programId, "projection"); - mTextureMatrixLoc = glGetUniformLocation(programId, "texture"); - mSamplerLoc = glGetUniformLocation(programId, "sampler"); - mColorLoc = glGetUniformLocation(programId, "color"); - mDisplayMaxLuminanceLoc = glGetUniformLocation(programId, "displayMaxLuminance"); - mInputTransformMatrixLoc = glGetUniformLocation(programId, "inputTransformMatrix"); - mOutputTransformMatrixLoc = glGetUniformLocation(programId, "outputTransformMatrix"); - - // set-up the default values for our uniforms - glUseProgram(programId); - glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, mat4().asArray()); - glEnableVertexAttribArray(0); - } -} - -Program::~Program() {} - -bool Program::isValid() const { - return mInitialized; -} - -void Program::use() { - glUseProgram(mProgram); -} - -GLuint Program::getAttrib(const char* name) const { - // TODO: maybe use a local cache - return glGetAttribLocation(mProgram, name); -} - -GLint Program::getUniform(const char* name) const { - // TODO: maybe use a local cache - return glGetUniformLocation(mProgram, name); -} - -GLuint Program::buildShader(const char* source, GLenum type) { - GLuint shader = glCreateShader(type); - glShaderSource(shader, 1, &source, 0); - glCompileShader(shader); - GLint status; - glGetShaderiv(shader, GL_COMPILE_STATUS, &status); - if (status != GL_TRUE) { - // Some drivers return wrong values for GL_INFO_LOG_LENGTH - // use a fixed size instead - GLchar log[512]; - glGetShaderInfoLog(shader, sizeof(log), 0, log); - ALOGE("Error while compiling shader: \n%s\n%s", source, log); - glDeleteShader(shader); - return 0; - } - return shader; -} - -String8& Program::dumpShader(String8& result, GLenum /*type*/) { - GLuint shader = GL_FRAGMENT_SHADER ? mFragmentShader : mVertexShader; - GLint l; - glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &l); - char* src = new char[l]; - glGetShaderSource(shader, l, nullptr, src); - result.append(src); - delete[] src; - return result; -} - -void Program::setUniforms(const Description& desc) { - // TODO: we should have a mechanism here to not always reset uniforms that - // didn't change for this program. - - if (mSamplerLoc >= 0) { - glUniform1i(mSamplerLoc, 0); - glUniformMatrix4fv(mTextureMatrixLoc, 1, GL_FALSE, desc.mTexture.getMatrix().asArray()); - } - if (mColorLoc >= 0) { - const float color[4] = {desc.mColor.r, desc.mColor.g, desc.mColor.b, desc.mColor.a}; - glUniform4fv(mColorLoc, 1, color); - } - if (mInputTransformMatrixLoc >= 0) { - mat4 inputTransformMatrix = mat4(desc.mInputTransformMatrix); - glUniformMatrix4fv(mInputTransformMatrixLoc, 1, GL_FALSE, inputTransformMatrix.asArray()); - } - if (mOutputTransformMatrixLoc >= 0) { - // The output transform matrix and color matrix can be combined as one matrix - // that is applied right before applying OETF. - mat4 outputTransformMatrix = desc.mColorMatrix * desc.mOutputTransformMatrix; - glUniformMatrix4fv(mOutputTransformMatrixLoc, 1, GL_FALSE, - outputTransformMatrix.asArray()); - } - if (mDisplayMaxLuminanceLoc >= 0) { - glUniform1f(mDisplayMaxLuminanceLoc, desc.mDisplayMaxLuminance); - } - // these uniforms are always present - glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, desc.mProjectionMatrix.asArray()); -} - -} /* namespace android */ diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp deleted file mode 100644 index b7101e05b7..0000000000 --- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp +++ /dev/null @@ -1,688 +0,0 @@ -/* - * Copyright 2013 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 ATRACE_TAG ATRACE_TAG_GRAPHICS - -#include - -#include -#include -#include -#include -#include -#include - -namespace android { -// ----------------------------------------------------------------------------------------------- - -/* - * A simple formatter class to automatically add the endl and - * manage the indentation. - */ - -class Formatter; -static Formatter& indent(Formatter& f); -static Formatter& dedent(Formatter& f); - -class Formatter { - String8 mString; - int mIndent; - typedef Formatter& (*FormaterManipFunc)(Formatter&); - friend Formatter& indent(Formatter& f); - friend Formatter& dedent(Formatter& f); - -public: - Formatter() : mIndent(0) {} - - String8 getString() const { return mString; } - - friend Formatter& operator<<(Formatter& out, const char* in) { - for (int i = 0; i < out.mIndent; i++) { - out.mString.append(" "); - } - out.mString.append(in); - out.mString.append("\n"); - return out; - } - friend inline Formatter& operator<<(Formatter& out, const String8& in) { - return operator<<(out, in.string()); - } - friend inline Formatter& operator<<(Formatter& to, FormaterManipFunc func) { - return (*func)(to); - } -}; -Formatter& indent(Formatter& f) { - f.mIndent++; - return f; -} -Formatter& dedent(Formatter& f) { - f.mIndent--; - return f; -} - -// ----------------------------------------------------------------------------------------------- - -ANDROID_SINGLETON_STATIC_INSTANCE(ProgramCache) - -ProgramCache::ProgramCache() {} - -ProgramCache::~ProgramCache() {} - -void ProgramCache::primeCache(bool useColorManagement) { - uint32_t shaderCount = 0; - uint32_t keyMask = Key::BLEND_MASK | Key::OPACITY_MASK | Key::ALPHA_MASK | Key::TEXTURE_MASK; - // Prime the cache for all combinations of the above masks, - // leaving off the experimental color matrix mask options. - - nsecs_t timeBefore = systemTime(); - for (uint32_t keyVal = 0; keyVal <= keyMask; keyVal++) { - Key shaderKey; - shaderKey.set(keyMask, keyVal); - uint32_t tex = shaderKey.getTextureTarget(); - if (tex != Key::TEXTURE_OFF && tex != Key::TEXTURE_EXT && tex != Key::TEXTURE_2D) { - continue; - } - Program* program = mCache.valueFor(shaderKey); - if (program == nullptr) { - program = generateProgram(shaderKey); - mCache.add(shaderKey, program); - shaderCount++; - } - } - - // Prime for sRGB->P3 conversion - if (useColorManagement) { - Key shaderKey; - shaderKey.set(Key::BLEND_MASK | Key::TEXTURE_MASK | Key::OUTPUT_TRANSFORM_MATRIX_MASK | - Key::INPUT_TF_MASK | Key::OUTPUT_TF_MASK, - Key::BLEND_PREMULT | Key::TEXTURE_EXT | Key::OUTPUT_TRANSFORM_MATRIX_ON | - Key::INPUT_TF_SRGB | Key::OUTPUT_TF_SRGB); - for (int i = 0; i < 4; i++) { - shaderKey.set(Key::OPACITY_MASK, - (i & 1) ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT); - shaderKey.set(Key::ALPHA_MASK, (i & 2) ? Key::ALPHA_LT_ONE : Key::ALPHA_EQ_ONE); - Program* program = mCache.valueFor(shaderKey); - if (program == nullptr) { - program = generateProgram(shaderKey); - mCache.add(shaderKey, program); - shaderCount++; - } - } - } - - nsecs_t timeAfter = systemTime(); - float compileTimeMs = static_cast(timeAfter - timeBefore) / 1.0E6; - ALOGD("shader cache generated - %u shaders in %f ms\n", shaderCount, compileTimeMs); -} - -ProgramCache::Key ProgramCache::computeKey(const Description& description) { - Key needs; - needs.set(Key::TEXTURE_MASK, - !description.mTextureEnabled - ? Key::TEXTURE_OFF - : description.mTexture.getTextureTarget() == GL_TEXTURE_EXTERNAL_OES - ? Key::TEXTURE_EXT - : description.mTexture.getTextureTarget() == GL_TEXTURE_2D - ? Key::TEXTURE_2D - : Key::TEXTURE_OFF) - .set(Key::ALPHA_MASK, - (description.mColor.a < 1) ? Key::ALPHA_LT_ONE : Key::ALPHA_EQ_ONE) - .set(Key::BLEND_MASK, - description.mPremultipliedAlpha ? Key::BLEND_PREMULT : Key::BLEND_NORMAL) - .set(Key::OPACITY_MASK, - description.mOpaque ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT) - .set(Key::Key::INPUT_TRANSFORM_MATRIX_MASK, - description.hasInputTransformMatrix() ? - Key::INPUT_TRANSFORM_MATRIX_ON : Key::INPUT_TRANSFORM_MATRIX_OFF) - .set(Key::Key::OUTPUT_TRANSFORM_MATRIX_MASK, - description.hasOutputTransformMatrix() || description.hasColorMatrix() ? - Key::OUTPUT_TRANSFORM_MATRIX_ON : Key::OUTPUT_TRANSFORM_MATRIX_OFF); - - needs.set(Key::Y410_BT2020_MASK, - description.mY410BT2020 ? Key::Y410_BT2020_ON : Key::Y410_BT2020_OFF); - - if (needs.hasTransformMatrix() || (needs.getInputTF() != needs.getOutputTF())) { - switch (description.mInputTransferFunction) { - case Description::TransferFunction::LINEAR: - default: - needs.set(Key::INPUT_TF_MASK, Key::INPUT_TF_LINEAR); - break; - case Description::TransferFunction::SRGB: - needs.set(Key::INPUT_TF_MASK, Key::INPUT_TF_SRGB); - break; - case Description::TransferFunction::ST2084: - needs.set(Key::INPUT_TF_MASK, Key::INPUT_TF_ST2084); - break; - case Description::TransferFunction::HLG: - needs.set(Key::INPUT_TF_MASK, Key::INPUT_TF_HLG); - break; - } - - switch (description.mOutputTransferFunction) { - case Description::TransferFunction::LINEAR: - default: - needs.set(Key::OUTPUT_TF_MASK, Key::OUTPUT_TF_LINEAR); - break; - case Description::TransferFunction::SRGB: - needs.set(Key::OUTPUT_TF_MASK, Key::OUTPUT_TF_SRGB); - break; - case Description::TransferFunction::ST2084: - needs.set(Key::OUTPUT_TF_MASK, Key::OUTPUT_TF_ST2084); - break; - case Description::TransferFunction::HLG: - needs.set(Key::OUTPUT_TF_MASK, Key::OUTPUT_TF_HLG); - break; - } - } - - return needs; -} - -// Generate EOTF that converts signal values to relative display light, -// both normalized to [0, 1]. -void ProgramCache::generateEOTF(Formatter& fs, const Key& needs) { - switch (needs.getInputTF()) { - case Key::INPUT_TF_SRGB: - fs << R"__SHADER__( - float EOTF_sRGB(float srgb) { - return srgb <= 0.04045 ? srgb / 12.92 : pow((srgb + 0.055) / 1.055, 2.4); - } - - vec3 EOTF_sRGB(const vec3 srgb) { - return vec3(EOTF_sRGB(srgb.r), EOTF_sRGB(srgb.g), EOTF_sRGB(srgb.b)); - } - - vec3 EOTF(const vec3 srgb) { - return sign(srgb.rgb) * EOTF_sRGB(abs(srgb.rgb)); - } - )__SHADER__"; - break; - case Key::INPUT_TF_ST2084: - fs << R"__SHADER__( - vec3 EOTF(const highp vec3 color) { - const highp float m1 = (2610.0 / 4096.0) / 4.0; - const highp float m2 = (2523.0 / 4096.0) * 128.0; - const highp float c1 = (3424.0 / 4096.0); - const highp float c2 = (2413.0 / 4096.0) * 32.0; - const highp float c3 = (2392.0 / 4096.0) * 32.0; - - highp vec3 tmp = pow(color, 1.0 / vec3(m2)); - tmp = max(tmp - c1, 0.0) / (c2 - c3 * tmp); - return pow(tmp, 1.0 / vec3(m1)); - } - )__SHADER__"; - break; - case Key::INPUT_TF_HLG: - fs << R"__SHADER__( - highp float EOTF_channel(const highp float channel) { - const highp float a = 0.17883277; - const highp float b = 0.28466892; - const highp float c = 0.55991073; - return channel <= 0.5 ? channel * channel / 3.0 : - (exp((channel - c) / a) + b) / 12.0; - } - - vec3 EOTF(const highp vec3 color) { - return vec3(EOTF_channel(color.r), EOTF_channel(color.g), - EOTF_channel(color.b)); - } - )__SHADER__"; - break; - default: - fs << R"__SHADER__( - vec3 EOTF(const vec3 linear) { - return linear; - } - )__SHADER__"; - break; - } -} - -void ProgramCache::generateToneMappingProcess(Formatter& fs, const Key& needs) { - // Convert relative light to absolute light. - switch (needs.getInputTF()) { - case Key::INPUT_TF_ST2084: - fs << R"__SHADER__( - highp vec3 ScaleLuminance(highp vec3 color) { - return color * 10000.0; - } - )__SHADER__"; - break; - case Key::INPUT_TF_HLG: - fs << R"__SHADER__( - highp vec3 ScaleLuminance(highp vec3 color) { - // The formula is: - // alpha * pow(Y, gamma - 1.0) * color + beta; - // where alpha is 1000.0, gamma is 1.2, beta is 0.0. - return color * 1000.0 * pow(color.y, 0.2); - } - )__SHADER__"; - break; - default: - fs << R"__SHADER__( - highp vec3 ScaleLuminance(highp vec3 color) { - return color * displayMaxLuminance; - } - )__SHADER__"; - break; - } - - // Tone map absolute light to display luminance range. - switch (needs.getInputTF()) { - case Key::INPUT_TF_ST2084: - case Key::INPUT_TF_HLG: - switch (needs.getOutputTF()) { - case Key::OUTPUT_TF_HLG: - // Right now when mixed PQ and HLG contents are presented, - // HLG content will always be converted to PQ. However, for - // completeness, we simply clamp the value to [0.0, 1000.0]. - fs << R"__SHADER__( - highp vec3 ToneMap(highp vec3 color) { - return clamp(color, 0.0, 1000.0); - } - )__SHADER__"; - break; - case Key::OUTPUT_TF_ST2084: - fs << R"__SHADER__( - highp vec3 ToneMap(highp vec3 color) { - return color; - } - )__SHADER__"; - break; - default: - fs << R"__SHADER__( - highp vec3 ToneMap(highp vec3 color) { - const float maxMasteringLumi = 1000.0; - const float maxContentLumi = 1000.0; - const float maxInLumi = min(maxMasteringLumi, maxContentLumi); - float maxOutLumi = displayMaxLuminance; - - float nits = color.y; - - // clamp to max input luminance - nits = clamp(nits, 0.0, maxInLumi); - - // scale [0.0, maxInLumi] to [0.0, maxOutLumi] - if (maxInLumi <= maxOutLumi) { - nits *= maxOutLumi / maxInLumi; - } else { - // three control points - const float x0 = 10.0; - const float y0 = 17.0; - float x1 = maxOutLumi * 0.75; - float y1 = x1; - float x2 = x1 + (maxInLumi - x1) / 2.0; - float y2 = y1 + (maxOutLumi - y1) * 0.75; - - // horizontal distances between the last three control points - float h12 = x2 - x1; - float h23 = maxInLumi - x2; - // tangents at the last three control points - float m1 = (y2 - y1) / h12; - float m3 = (maxOutLumi - y2) / h23; - float m2 = (m1 + m3) / 2.0; - - if (nits < x0) { - // scale [0.0, x0] to [0.0, y0] linearly - float slope = y0 / x0; - nits *= slope; - } else if (nits < x1) { - // scale [x0, x1] to [y0, y1] linearly - float slope = (y1 - y0) / (x1 - x0); - nits = y0 + (nits - x0) * slope; - } else if (nits < x2) { - // scale [x1, x2] to [y1, y2] using Hermite interp - float t = (nits - x1) / h12; - nits = (y1 * (1.0 + 2.0 * t) + h12 * m1 * t) * (1.0 - t) * (1.0 - t) + - (y2 * (3.0 - 2.0 * t) + h12 * m2 * (t - 1.0)) * t * t; - } else { - // scale [x2, maxInLumi] to [y2, maxOutLumi] using Hermite interp - float t = (nits - x2) / h23; - nits = (y2 * (1.0 + 2.0 * t) + h23 * m2 * t) * (1.0 - t) * (1.0 - t) + - (maxOutLumi * (3.0 - 2.0 * t) + h23 * m3 * (t - 1.0)) * t * t; - } - } - - return color * (nits / max(1e-6, color.y)); - } - )__SHADER__"; - break; - } - break; - default: - // inverse tone map; the output luminance can be up to maxOutLumi. - fs << R"__SHADER__( - highp vec3 ToneMap(highp vec3 color) { - const float maxOutLumi = 3000.0; - - const float x0 = 5.0; - const float y0 = 2.5; - float x1 = displayMaxLuminance * 0.7; - float y1 = maxOutLumi * 0.15; - float x2 = displayMaxLuminance * 0.9; - float y2 = maxOutLumi * 0.45; - float x3 = displayMaxLuminance; - float y3 = maxOutLumi; - - float c1 = y1 / 3.0; - float c2 = y2 / 2.0; - float c3 = y3 / 1.5; - - float nits = color.y; - - float scale; - if (nits <= x0) { - // scale [0.0, x0] to [0.0, y0] linearly - const float slope = y0 / x0; - nits *= slope; - } else if (nits <= x1) { - // scale [x0, x1] to [y0, y1] using a curve - float t = (nits - x0) / (x1 - x0); - nits = (1.0 - t) * (1.0 - t) * y0 + 2.0 * (1.0 - t) * t * c1 + t * t * y1; - } else if (nits <= x2) { - // scale [x1, x2] to [y1, y2] using a curve - float t = (nits - x1) / (x2 - x1); - nits = (1.0 - t) * (1.0 - t) * y1 + 2.0 * (1.0 - t) * t * c2 + t * t * y2; - } else { - // scale [x2, x3] to [y2, y3] using a curve - float t = (nits - x2) / (x3 - x2); - nits = (1.0 - t) * (1.0 - t) * y2 + 2.0 * (1.0 - t) * t * c3 + t * t * y3; - } - - return color * (nits / max(1e-6, color.y)); - } - )__SHADER__"; - break; - } - - // convert absolute light to relative light. - switch (needs.getOutputTF()) { - case Key::OUTPUT_TF_ST2084: - fs << R"__SHADER__( - highp vec3 NormalizeLuminance(highp vec3 color) { - return color / 10000.0; - } - )__SHADER__"; - break; - case Key::OUTPUT_TF_HLG: - fs << R"__SHADER__( - highp vec3 NormalizeLuminance(highp vec3 color) { - return color / 1000.0 * pow(color.y / 1000.0, -0.2 / 1.2); - } - )__SHADER__"; - break; - default: - fs << R"__SHADER__( - highp vec3 NormalizeLuminance(highp vec3 color) { - return color / displayMaxLuminance; - } - )__SHADER__"; - break; - } -} - -// Generate OOTF that modifies the relative scence light to relative display light. -void ProgramCache::generateOOTF(Formatter& fs, const ProgramCache::Key& needs) { - if (!needs.needsToneMapping()) { - fs << R"__SHADER__( - highp vec3 OOTF(const highp vec3 color) { - return color; - } - )__SHADER__"; - } else { - generateToneMappingProcess(fs, needs); - fs << R"__SHADER__( - highp vec3 OOTF(const highp vec3 color) { - return NormalizeLuminance(ToneMap(ScaleLuminance(color))); - } - )__SHADER__"; - } -} - -// Generate OETF that converts relative display light to signal values, -// both normalized to [0, 1] -void ProgramCache::generateOETF(Formatter& fs, const Key& needs) { - switch (needs.getOutputTF()) { - case Key::OUTPUT_TF_SRGB: - fs << R"__SHADER__( - float OETF_sRGB(const float linear) { - return linear <= 0.0031308 ? - linear * 12.92 : (pow(linear, 1.0 / 2.4) * 1.055) - 0.055; - } - - vec3 OETF_sRGB(const vec3 linear) { - return vec3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b)); - } - - vec3 OETF(const vec3 linear) { - return sign(linear.rgb) * OETF_sRGB(abs(linear.rgb)); - } - )__SHADER__"; - break; - case Key::OUTPUT_TF_ST2084: - fs << R"__SHADER__( - vec3 OETF(const vec3 linear) { - const highp float m1 = (2610.0 / 4096.0) / 4.0; - const highp float m2 = (2523.0 / 4096.0) * 128.0; - const highp float c1 = (3424.0 / 4096.0); - const highp float c2 = (2413.0 / 4096.0) * 32.0; - const highp float c3 = (2392.0 / 4096.0) * 32.0; - - highp vec3 tmp = pow(linear, vec3(m1)); - tmp = (c1 + c2 * tmp) / (1.0 + c3 * tmp); - return pow(tmp, vec3(m2)); - } - )__SHADER__"; - break; - case Key::OUTPUT_TF_HLG: - fs << R"__SHADER__( - highp float OETF_channel(const highp float channel) { - const highp float a = 0.17883277; - const highp float b = 0.28466892; - const highp float c = 0.55991073; - return channel <= 1.0 / 12.0 ? sqrt(3.0 * channel) : - a * log(12.0 * channel - b) + c; - } - - vec3 OETF(const highp vec3 color) { - return vec3(OETF_channel(color.r), OETF_channel(color.g), - OETF_channel(color.b)); - } - )__SHADER__"; - break; - default: - fs << R"__SHADER__( - vec3 OETF(const vec3 linear) { - return linear; - } - )__SHADER__"; - break; - } -} - -String8 ProgramCache::generateVertexShader(const Key& needs) { - Formatter vs; - if (needs.isTexturing()) { - vs << "attribute vec4 texCoords;" - << "varying vec2 outTexCoords;"; - } - vs << "attribute vec4 position;" - << "uniform mat4 projection;" - << "uniform mat4 texture;" - << "void main(void) {" << indent << "gl_Position = projection * position;"; - if (needs.isTexturing()) { - vs << "outTexCoords = (texture * texCoords).st;"; - } - vs << dedent << "}"; - return vs.getString(); -} - -String8 ProgramCache::generateFragmentShader(const Key& needs) { - Formatter fs; - if (needs.getTextureTarget() == Key::TEXTURE_EXT) { - fs << "#extension GL_OES_EGL_image_external : require"; - } - - // default precision is required-ish in fragment shaders - fs << "precision mediump float;"; - - if (needs.getTextureTarget() == Key::TEXTURE_EXT) { - fs << "uniform samplerExternalOES sampler;" - << "varying vec2 outTexCoords;"; - } else if (needs.getTextureTarget() == Key::TEXTURE_2D) { - fs << "uniform sampler2D sampler;" - << "varying vec2 outTexCoords;"; - } - - if (needs.getTextureTarget() == Key::TEXTURE_OFF || needs.hasAlpha()) { - fs << "uniform vec4 color;"; - } - - if (needs.isY410BT2020()) { - fs << R"__SHADER__( - vec3 convertY410BT2020(const vec3 color) { - const vec3 offset = vec3(0.0625, 0.5, 0.5); - const mat3 transform = mat3( - vec3(1.1678, 1.1678, 1.1678), - vec3( 0.0, -0.1878, 2.1481), - vec3(1.6836, -0.6523, 0.0)); - // Y is in G, U is in R, and V is in B - return clamp(transform * (color.grb - offset), 0.0, 1.0); - } - )__SHADER__"; - } - - if (needs.hasTransformMatrix() || (needs.getInputTF() != needs.getOutputTF())) { - // Currently, display maximum luminance is needed when doing tone mapping. - if (needs.needsToneMapping()) { - fs << "uniform float displayMaxLuminance;"; - } - - if (needs.hasInputTransformMatrix()) { - fs << "uniform mat4 inputTransformMatrix;"; - fs << R"__SHADER__( - highp vec3 InputTransform(const highp vec3 color) { - return vec3(inputTransformMatrix * vec4(color, 1.0)); - } - )__SHADER__"; - } else { - fs << R"__SHADER__( - highp vec3 InputTransform(const highp vec3 color) { - return color; - } - )__SHADER__"; - } - - // the transformation from a wider colorspace to a narrower one can - // result in >1.0 or <0.0 pixel values - if (needs.hasOutputTransformMatrix()) { - fs << "uniform mat4 outputTransformMatrix;"; - fs << R"__SHADER__( - highp vec3 OutputTransform(const highp vec3 color) { - return clamp(vec3(outputTransformMatrix * vec4(color, 1.0)), 0.0, 1.0); - } - )__SHADER__"; - } else { - fs << R"__SHADER__( - highp vec3 OutputTransform(const highp vec3 color) { - return clamp(color, 0.0, 1.0); - } - )__SHADER__"; - } - - generateEOTF(fs, needs); - generateOOTF(fs, needs); - generateOETF(fs, needs); - } - - fs << "void main(void) {" << indent; - if (needs.isTexturing()) { - fs << "gl_FragColor = texture2D(sampler, outTexCoords);"; - if (needs.isY410BT2020()) { - fs << "gl_FragColor.rgb = convertY410BT2020(gl_FragColor.rgb);"; - } - } else { - fs << "gl_FragColor.rgb = color.rgb;"; - fs << "gl_FragColor.a = 1.0;"; - } - if (needs.isOpaque()) { - fs << "gl_FragColor.a = 1.0;"; - } - if (needs.hasAlpha()) { - // modulate the current alpha value with alpha set - if (needs.isPremultiplied()) { - // ... and the color too if we're premultiplied - fs << "gl_FragColor *= color.a;"; - } else { - fs << "gl_FragColor.a *= color.a;"; - } - } - - if (needs.hasTransformMatrix() || (needs.getInputTF() != needs.getOutputTF())) { - if (!needs.isOpaque() && needs.isPremultiplied()) { - // un-premultiply if needed before linearization - // avoid divide by 0 by adding 0.5/256 to the alpha channel - fs << "gl_FragColor.rgb = gl_FragColor.rgb / (gl_FragColor.a + 0.0019);"; - } - fs << "gl_FragColor.rgb = OETF(OutputTransform(OOTF(InputTransform(EOTF(gl_FragColor.rgb)))));"; - if (!needs.isOpaque() && needs.isPremultiplied()) { - // and re-premultiply if needed after gamma correction - fs << "gl_FragColor.rgb = gl_FragColor.rgb * (gl_FragColor.a + 0.0019);"; - } - } - - fs << dedent << "}"; - return fs.getString(); -} - -Program* ProgramCache::generateProgram(const Key& needs) { - ATRACE_CALL(); - - // vertex shader - String8 vs = generateVertexShader(needs); - - // fragment shader - String8 fs = generateFragmentShader(needs); - - Program* program = new Program(needs, vs.string(), fs.string()); - return program; -} - -void ProgramCache::useProgram(const Description& description) { - // generate the key for the shader based on the description - Key needs(computeKey(description)); - - // look-up the program in the cache - Program* program = mCache.valueFor(needs); - if (program == nullptr) { - // we didn't find our program, so generate one... - nsecs_t time = -systemTime(); - program = generateProgram(needs); - mCache.add(needs, program); - time += systemTime(); - - ALOGV(">>> generated new program: needs=%08X, time=%u ms (%zu programs)", needs.mKey, - uint32_t(ns2ms(time)), mCache.size()); - } - - // here we have a suitable program for this description - if (program->isValid()) { - program->use(); - program->setUniforms(description); - } -} - -} /* namespace android */ diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index 594b1eda06..c843428bc6 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -16,29 +16,30 @@ #include +#include + #include #include #include #include -#include -#include #include #include #include #include #include - -#include +#include +#include "gl/GLES20RenderEngine.h" +#include "gl/GLExtensions.h" +#include "gl/ProgramCache.h" using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; +using namespace android::renderengine::gl; extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name); -// --------------------------------------------------------------------------- namespace android { -namespace RE { -// --------------------------------------------------------------------------- +namespace renderengine { RenderEngine::~RenderEngine() = default; @@ -187,22 +188,22 @@ bool RenderEngine::isCurrent() const { return mEGLDisplay == eglGetCurrentDisplay() && mEGLContext == eglGetCurrentContext(); } -std::unique_ptr RenderEngine::createSurface() { +std::unique_ptr RenderEngine::createSurface() { return std::make_unique(*this); } -std::unique_ptr RenderEngine::createImage() { +std::unique_ptr RenderEngine::createImage() { return std::make_unique(*this); } -bool RenderEngine::setCurrentSurface(const android::RE::Surface& surface) { - // Note: RE::Surface is an abstract interface. This implementation only ever - // creates RE::impl::Surface's, so it is safe to just cast to the actual +bool RenderEngine::setCurrentSurface(const android::renderengine::Surface& surface) { + // Note: renderengine::Surface is an abstract interface. This implementation only ever + // creates renderengine::impl::Surface's, so it is safe to just cast to the actual // type. - return setCurrentSurface(static_cast(surface)); + return setCurrentSurface(static_cast(surface)); } -bool RenderEngine::setCurrentSurface(const android::RE::impl::Surface& surface) { +bool RenderEngine::setCurrentSurface(const android::renderengine::impl::Surface& surface) { bool success = true; EGLSurface eglSurface = surface.getEGLSurface(); if (eglSurface != eglGetCurrentSurface(EGL_DRAW)) { @@ -374,14 +375,16 @@ void RenderEngine::deleteTextures(size_t count, uint32_t const* names) { glDeleteTextures(count, names); } -void RenderEngine::bindExternalTextureImage(uint32_t texName, const android::RE::Image& image) { - // Note: RE::Image is an abstract interface. This implementation only ever - // creates RE::impl::Image's, so it is safe to just cast to the actual type. - return bindExternalTextureImage(texName, static_cast(image)); +void RenderEngine::bindExternalTextureImage(uint32_t texName, + const android::renderengine::Image& image) { + // Note: renderengine::Image is an abstract interface. This implementation only ever + // creates renderengine::impl::Image's, so it is safe to just cast to the actual type. + return bindExternalTextureImage(texName, + static_cast(image)); } void RenderEngine::bindExternalTextureImage(uint32_t texName, - const android::RE::impl::Image& image) { + const android::renderengine::impl::Image& image) { const GLenum target = GL_TEXTURE_EXTERNAL_OES; glBindTexture(target, texName); @@ -405,10 +408,9 @@ void RenderEngine::dump(String8& result) { result.appendFormat("%s\n", extensions.getExtensions()); } -// --------------------------------------------------------------------------- - -void RenderEngine::bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer, - RE::BindNativeBufferAsFramebuffer* bindHelper) { +void RenderEngine::bindNativeBufferAsFrameBuffer( + ANativeWindowBuffer* buffer, + renderengine::BindNativeBufferAsFramebuffer* bindHelper) { bindHelper->mImage = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, buffer, nullptr); if (bindHelper->mImage == EGL_NO_IMAGE_KHR) { @@ -426,7 +428,8 @@ void RenderEngine::bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer, bindHelper->mStatus = glStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE; } -void RenderEngine::unbindNativeBufferAsFrameBuffer(RE::BindNativeBufferAsFramebuffer* bindHelper) { +void RenderEngine::unbindNativeBufferAsFrameBuffer( + renderengine::BindNativeBufferAsFramebuffer* bindHelper) { if (bindHelper->mImage == EGL_NO_IMAGE_KHR) { return; } @@ -598,8 +601,7 @@ void RenderEngine::primeCache() const { ProgramCache::getInstance().primeCache(mFeatureFlags & USE_COLOR_MANAGEMENT); } -// --------------------------------------------------------------------------- -} // namespace impl -} // namespace RE -} // namespace android +} // namespace impl +} // namespace renderengine +} // namespace android diff --git a/services/surfaceflinger/RenderEngine/Surface.cpp b/services/surfaceflinger/RenderEngine/Surface.cpp index 3e98ab4f5e..b9f095b543 100644 --- a/services/surfaceflinger/RenderEngine/Surface.cpp +++ b/services/surfaceflinger/RenderEngine/Surface.cpp @@ -21,7 +21,7 @@ #include namespace android { -namespace RE { +namespace renderengine { Surface::~Surface() = default; @@ -106,6 +106,6 @@ int32_t Surface::queryHeight() const { return querySurface(EGL_HEIGHT); } -} // namespace impl -} // namespace RE -} // namespace android +} // namespace impl +} // namespace renderengine +} // namespace android diff --git a/services/surfaceflinger/RenderEngine/Texture.cpp b/services/surfaceflinger/RenderEngine/Texture.cpp index c07ba085ee..5eabbcf03e 100644 --- a/services/surfaceflinger/RenderEngine/Texture.cpp +++ b/services/surfaceflinger/RenderEngine/Texture.cpp @@ -16,9 +16,8 @@ #include -#include - namespace android { +namespace renderengine { Texture::Texture() : mTextureName(0), mTextureTarget(TEXTURE_2D), mWidth(0), mHeight(0), mFiltering(false) {} @@ -74,4 +73,5 @@ size_t Texture::getHeight() const { return mHeight; } -} /* namespace android */ +} // namespace renderengine +} // namespace android diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp new file mode 100644 index 0000000000..e0f1850faa --- /dev/null +++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp @@ -0,0 +1,468 @@ +/* + * Copyright 2013 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 "RenderEngine" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "GLES20RenderEngine.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Program.h" +#include "ProgramCache.h" + +bool checkGlError(const char* op, int lineNumber) { + bool errorFound = false; + GLint error = glGetError(); + while (error != GL_NO_ERROR) { + errorFound = true; + error = glGetError(); + ALOGV("after %s() (line # %d) glError (0x%x)\n", op, lineNumber, error); + } + return errorFound; +} + +static constexpr bool outputDebugPPMs = false; + +void writePPM(const char* basename, GLuint width, GLuint height) { + ALOGV("writePPM #%s: %d x %d", basename, width, height); + + std::vector pixels(width * height * 4); + std::vector outBuffer(width * height * 3); + + // TODO(courtneygo): We can now have float formats, need + // to remove this code or update to support. + // Make returned pixels fit in uint32_t, one byte per component + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); + if (checkGlError(__FUNCTION__, __LINE__)) { + return; + } + + std::string filename(basename); + filename.append(".ppm"); + std::ofstream file(filename.c_str(), std::ios::binary); + if (!file.is_open()) { + ALOGE("Unable to open file: %s", filename.c_str()); + ALOGE("You may need to do: \"adb shell setenforce 0\" to enable " + "surfaceflinger to write debug images"); + return; + } + + file << "P6\n"; + file << width << "\n"; + file << height << "\n"; + file << 255 << "\n"; + + auto ptr = reinterpret_cast(pixels.data()); + auto outPtr = reinterpret_cast(outBuffer.data()); + for (int y = height - 1; y >= 0; y--) { + char* data = ptr + y * width * sizeof(uint32_t); + + for (GLuint x = 0; x < width; x++) { + // Only copy R, G and B components + outPtr[0] = data[0]; + outPtr[1] = data[1]; + outPtr[2] = data[2]; + data += sizeof(uint32_t); + outPtr += 3; + } + } + file.write(reinterpret_cast(outBuffer.data()), outBuffer.size()); +} + +namespace android { +namespace renderengine { +namespace gl { + +using ui::Dataspace; + +GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags) + : RenderEngine(featureFlags), + mVpWidth(0), + mVpHeight(0), + mUseColorManagement(featureFlags & USE_COLOR_MANAGEMENT) { + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); + glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glPixelStorei(GL_PACK_ALIGNMENT, 4); + + const uint16_t protTexData[] = {0}; + glGenTextures(1, &mProtectedTexName); + glBindTexture(GL_TEXTURE_2D, mProtectedTexName); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData); + + // mColorBlindnessCorrection = M; + + if (mUseColorManagement) { + ColorSpace srgb(ColorSpace::sRGB()); + ColorSpace displayP3(ColorSpace::DisplayP3()); + ColorSpace bt2020(ColorSpace::BT2020()); + + // Compute sRGB to Display P3 transform matrix. + // NOTE: For now, we are limiting output wide color space support to + // Display-P3 only. + mSrgbToDisplayP3 = mat4(ColorSpaceConnector(srgb, displayP3).getTransform()); + + // Compute Display P3 to sRGB transform matrix. + mDisplayP3ToSrgb = mat4(ColorSpaceConnector(displayP3, srgb).getTransform()); + + // no chromatic adaptation needed since all color spaces use D65 for their white points. + mSrgbToXyz = srgb.getRGBtoXYZ(); + mDisplayP3ToXyz = displayP3.getRGBtoXYZ(); + mBt2020ToXyz = bt2020.getRGBtoXYZ(); + mXyzToSrgb = mat4(srgb.getXYZtoRGB()); + mXyzToDisplayP3 = mat4(displayP3.getXYZtoRGB()); + mXyzToBt2020 = mat4(bt2020.getXYZtoRGB()); + } +} + +GLES20RenderEngine::~GLES20RenderEngine() {} + +size_t GLES20RenderEngine::getMaxTextureSize() const { + return mMaxTextureSize; +} + +size_t GLES20RenderEngine::getMaxViewportDims() const { + return mMaxViewportDims[0] < mMaxViewportDims[1] ? mMaxViewportDims[0] : mMaxViewportDims[1]; +} + +void GLES20RenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, + size_t hwh, bool yswap, + ui::Transform::orientation_flags rotation) { + int32_t l = sourceCrop.left; + int32_t r = sourceCrop.right; + + // In GL, (0, 0) is the bottom-left corner, so flip y coordinates + int32_t t = hwh - sourceCrop.top; + int32_t b = hwh - sourceCrop.bottom; + + mat4 m; + if (yswap) { + m = mat4::ortho(l, r, t, b, 0, 1); + } else { + m = mat4::ortho(l, r, b, t, 0, 1); + } + + // Apply custom rotation to the projection. + float rot90InRadians = 2.0f * static_cast(M_PI) / 4.0f; + switch (rotation) { + case ui::Transform::ROT_0: + break; + case ui::Transform::ROT_90: + m = mat4::rotate(rot90InRadians, vec3(0, 0, 1)) * m; + break; + case ui::Transform::ROT_180: + m = mat4::rotate(rot90InRadians * 2.0f, vec3(0, 0, 1)) * m; + break; + case ui::Transform::ROT_270: + m = mat4::rotate(rot90InRadians * 3.0f, vec3(0, 0, 1)) * m; + break; + default: + break; + } + + glViewport(0, 0, vpw, vph); + mState.setProjectionMatrix(m); + mVpWidth = vpw; + mVpHeight = vph; +} + +void GLES20RenderEngine::setupLayerBlending(bool premultipliedAlpha, bool opaque, + bool disableTexture, const half4& color) { + mState.setPremultipliedAlpha(premultipliedAlpha); + mState.setOpaque(opaque); + mState.setColor(color); + + if (disableTexture) { + mState.disableTexture(); + } + + if (color.a < 1.0f || !opaque) { + glEnable(GL_BLEND); + glBlendFunc(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } else { + glDisable(GL_BLEND); + } +} + +void GLES20RenderEngine::setSourceY410BT2020(bool enable) { + mState.setY410BT2020(enable); +} + +void GLES20RenderEngine::setSourceDataSpace(Dataspace source) { + mDataSpace = source; +} + +void GLES20RenderEngine::setOutputDataSpace(Dataspace dataspace) { + mOutputDataSpace = dataspace; +} + +void GLES20RenderEngine::setDisplayMaxLuminance(const float maxLuminance) { + mState.setDisplayMaxLuminance(maxLuminance); +} + +void GLES20RenderEngine::setupLayerTexturing(const Texture& texture) { + GLuint target = texture.getTextureTarget(); + glBindTexture(target, texture.getTextureName()); + GLenum filter = GL_NEAREST; + if (texture.getFiltering()) { + filter = GL_LINEAR; + } + glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter); + + mState.setTexture(texture); +} + +void GLES20RenderEngine::setupLayerBlackedOut() { + glBindTexture(GL_TEXTURE_2D, mProtectedTexName); + Texture texture(Texture::TEXTURE_2D, mProtectedTexName); + texture.setDimensions(1, 1); // FIXME: we should get that from somewhere + mState.setTexture(texture); +} + +void GLES20RenderEngine::setupColorTransform(const mat4& colorTransform) { + mState.setColorMatrix(colorTransform); +} + +void GLES20RenderEngine::disableTexturing() { + mState.disableTexture(); +} + +void GLES20RenderEngine::disableBlending() { + glDisable(GL_BLEND); +} + +void GLES20RenderEngine::bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, + uint32_t* fbName, uint32_t* status) { + GLuint tname, name; + // turn our EGLImage into a texture + glGenTextures(1, &tname); + glBindTexture(GL_TEXTURE_2D, tname); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); + + // create a Framebuffer Object to render into + glGenFramebuffers(1, &name); + glBindFramebuffer(GL_FRAMEBUFFER, name); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0); + + *status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + *texName = tname; + *fbName = name; +} + +void GLES20RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName) { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDeleteFramebuffers(1, &fbName); + glDeleteTextures(1, &texName); +} + +void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) { + mState.setPremultipliedAlpha(true); + mState.setOpaque(false); + mState.setColor(half4(r, g, b, a)); + mState.disableTexture(); + glDisable(GL_BLEND); +} + +void GLES20RenderEngine::drawMesh(const Mesh& mesh) { + ATRACE_CALL(); + if (mesh.getTexCoordsSize()) { + glEnableVertexAttribArray(Program::texCoords); + glVertexAttribPointer(Program::texCoords, mesh.getTexCoordsSize(), GL_FLOAT, GL_FALSE, + mesh.getByteStride(), mesh.getTexCoords()); + } + + glVertexAttribPointer(Program::position, mesh.getVertexSize(), GL_FLOAT, GL_FALSE, + mesh.getByteStride(), mesh.getPositions()); + + // By default, DISPLAY_P3 is the only supported wide color output. However, + // when HDR content is present, hardware composer may be able to handle + // BT2020 data space, in that case, the output data space is set to be + // BT2020_HLG or BT2020_PQ respectively. In GPU fall back we need + // to respect this and convert non-HDR content to HDR format. + if (mUseColorManagement) { + Description managedState = mState; + Dataspace inputStandard = static_cast(mDataSpace & Dataspace::STANDARD_MASK); + Dataspace inputTransfer = static_cast(mDataSpace & Dataspace::TRANSFER_MASK); + Dataspace outputStandard = static_cast(mOutputDataSpace & + Dataspace::STANDARD_MASK); + Dataspace outputTransfer = static_cast(mOutputDataSpace & + Dataspace::TRANSFER_MASK); + bool needsXYZConversion = needsXYZTransformMatrix(); + + if (needsXYZConversion) { + // The supported input color spaces are standard RGB, Display P3 and BT2020. + switch (inputStandard) { + case Dataspace::STANDARD_DCI_P3: + managedState.setInputTransformMatrix(mDisplayP3ToXyz); + break; + case Dataspace::STANDARD_BT2020: + managedState.setInputTransformMatrix(mBt2020ToXyz); + break; + default: + managedState.setInputTransformMatrix(mSrgbToXyz); + break; + } + + // The supported output color spaces are BT2020, Display P3 and standard RGB. + switch (outputStandard) { + case Dataspace::STANDARD_BT2020: + managedState.setOutputTransformMatrix(mXyzToBt2020); + break; + case Dataspace::STANDARD_DCI_P3: + managedState.setOutputTransformMatrix(mXyzToDisplayP3); + break; + default: + managedState.setOutputTransformMatrix(mXyzToSrgb); + break; + } + } else if (inputStandard != outputStandard) { + // At this point, the input data space and output data space could be both + // HDR data spaces, but they match each other, we do nothing in this case. + // In addition to the case above, the input data space could be + // - scRGB linear + // - scRGB non-linear + // - sRGB + // - Display P3 + // The output data spaces could be + // - sRGB + // - Display P3 + if (outputStandard == Dataspace::STANDARD_BT709) { + managedState.setOutputTransformMatrix(mDisplayP3ToSrgb); + } else if (outputStandard == Dataspace::STANDARD_DCI_P3) { + managedState.setOutputTransformMatrix(mSrgbToDisplayP3); + } + } + + // we need to convert the RGB value to linear space and convert it back when: + // - there is a color matrix that is not an identity matrix, or + // - there is an output transform matrix that is not an identity matrix, or + // - the input transfer function doesn't match the output transfer function. + if (managedState.hasColorMatrix() || managedState.hasOutputTransformMatrix() || + inputTransfer != outputTransfer) { + switch (inputTransfer) { + case Dataspace::TRANSFER_ST2084: + managedState.setInputTransferFunction(Description::TransferFunction::ST2084); + break; + case Dataspace::TRANSFER_HLG: + managedState.setInputTransferFunction(Description::TransferFunction::HLG); + break; + case Dataspace::TRANSFER_LINEAR: + managedState.setInputTransferFunction(Description::TransferFunction::LINEAR); + break; + default: + managedState.setInputTransferFunction(Description::TransferFunction::SRGB); + break; + } + + switch (outputTransfer) { + case Dataspace::TRANSFER_ST2084: + managedState.setOutputTransferFunction(Description::TransferFunction::ST2084); + break; + case Dataspace::TRANSFER_HLG: + managedState.setOutputTransferFunction(Description::TransferFunction::HLG); + break; + default: + managedState.setOutputTransferFunction(Description::TransferFunction::SRGB); + break; + } + } + + ProgramCache::getInstance().useProgram(managedState); + + glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount()); + + if (outputDebugPPMs) { + static uint64_t managedColorFrameCount = 0; + std::ostringstream out; + out << "/data/texture_out" << managedColorFrameCount++; + writePPM(out.str().c_str(), mVpWidth, mVpHeight); + } + } else { + ProgramCache::getInstance().useProgram(mState); + + glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount()); + } + + if (mesh.getTexCoordsSize()) { + glDisableVertexAttribArray(Program::texCoords); + } +} + +void GLES20RenderEngine::dump(String8& result) { + RenderEngine::dump(result); + result.appendFormat("RenderEngine last dataspace conversion: (%s) to (%s)\n", + dataspaceDetails(static_cast(mDataSpace)).c_str(), + dataspaceDetails(static_cast(mOutputDataSpace)).c_str()); +} + +bool GLES20RenderEngine::isHdrDataSpace(const Dataspace dataSpace) const { + const Dataspace standard = static_cast(dataSpace & Dataspace::STANDARD_MASK); + const Dataspace transfer = static_cast(dataSpace & Dataspace::TRANSFER_MASK); + return standard == Dataspace::STANDARD_BT2020 && + (transfer == Dataspace::TRANSFER_ST2084 || transfer == Dataspace::TRANSFER_HLG); +} + +// For convenience, we want to convert the input color space to XYZ color space first, +// and then convert from XYZ color space to output color space when +// - SDR and HDR contents are mixed, either SDR content will be converted to HDR or +// HDR content will be tone-mapped to SDR; Or, +// - there are HDR PQ and HLG contents presented at the same time, where we want to convert +// HLG content to PQ content. +// In either case above, we need to operate the Y value in XYZ color space. Thus, when either +// input data space or output data space is HDR data space, and the input transfer function +// doesn't match the output transfer function, we would enable an intermediate transfrom to +// XYZ color space. +bool GLES20RenderEngine::needsXYZTransformMatrix() const { + const bool isInputHdrDataSpace = isHdrDataSpace(mDataSpace); + const bool isOutputHdrDataSpace = isHdrDataSpace(mOutputDataSpace); + const Dataspace inputTransfer = static_cast(mDataSpace & Dataspace::TRANSFER_MASK); + const Dataspace outputTransfer = static_cast(mOutputDataSpace & + Dataspace::TRANSFER_MASK); + + return (isInputHdrDataSpace || isOutputHdrDataSpace) && inputTransfer != outputTransfer; +} + +} // namespace gl +} // namespace renderengine +} // namespace android + +#if defined(__gl_h_) +#error "don't include gl/gl.h in this file" +#endif diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h new file mode 100644 index 0000000000..c830184bfa --- /dev/null +++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h @@ -0,0 +1,117 @@ +/* + * Copyright 2013 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. + */ + +#ifndef SF_GLES20RENDERENGINE_H_ +#define SF_GLES20RENDERENGINE_H_ + +#include +#include + +#include +#include +#include + +namespace android { + +class String8; + +namespace renderengine { + +class Mesh; +class Texture; + +namespace gl { + +class GLES20RenderEngine : public impl::RenderEngine { + GLuint mProtectedTexName; + GLint mMaxViewportDims[2]; + GLint mMaxTextureSize; + GLuint mVpWidth; + GLuint mVpHeight; + + struct Group { + GLuint texture; + GLuint fbo; + GLuint width; + GLuint height; + mat4 colorTransform; + }; + + Description mState; + + virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, + uint32_t* status); + virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName); + +public: + GLES20RenderEngine(uint32_t featureFlags); // See RenderEngine::FeatureFlag + virtual ~GLES20RenderEngine(); + +protected: + virtual void dump(String8& result); + virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, + bool yswap, ui::Transform::orientation_flags rotation); + virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture, + const half4& color) override; + + // Color management related functions and state + void setSourceY410BT2020(bool enable) override; + void setSourceDataSpace(ui::Dataspace source) override; + void setOutputDataSpace(ui::Dataspace dataspace) override; + void setDisplayMaxLuminance(const float maxLuminance) override; + + virtual void setupLayerTexturing(const Texture& texture); + virtual void setupLayerBlackedOut(); + virtual void setupFillWithColor(float r, float g, float b, float a); + virtual void setupColorTransform(const mat4& colorTransform); + virtual void disableTexturing(); + virtual void disableBlending(); + + virtual void drawMesh(const Mesh& mesh); + + virtual size_t getMaxTextureSize() const; + virtual size_t getMaxViewportDims() const; + + // Current dataspace of layer being rendered + ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN; + + // Current output dataspace of the render engine + ui::Dataspace mOutputDataSpace = ui::Dataspace::UNKNOWN; + + // Whether device supports color management, currently color management + // supports sRGB, DisplayP3 color spaces. + const bool mUseColorManagement = false; + mat4 mSrgbToDisplayP3; + mat4 mDisplayP3ToSrgb; + mat3 mSrgbToXyz; + mat3 mBt2020ToXyz; + mat3 mDisplayP3ToXyz; + mat4 mXyzToSrgb; + mat4 mXyzToDisplayP3; + mat4 mXyzToBt2020; + +private: + // A data space is considered HDR data space if it has BT2020 color space + // with PQ or HLG transfer function. + bool isHdrDataSpace(const ui::Dataspace dataSpace) const; + bool needsXYZTransformMatrix() const; +}; + +} // namespace gl +} // namespace renderengine +} // namespace android + +#endif /* SF_GLES20RENDERENGINE_H_ */ diff --git a/services/surfaceflinger/RenderEngine/gl/GLExtensions.cpp b/services/surfaceflinger/RenderEngine/gl/GLExtensions.cpp new file mode 100644 index 0000000000..6f50ea7df2 --- /dev/null +++ b/services/surfaceflinger/RenderEngine/gl/GLExtensions.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2010 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. + */ + +#include "GLExtensions.h" + +#include +#include +#include + +ANDROID_SINGLETON_STATIC_INSTANCE(android::renderengine::gl::GLExtensions) + +namespace android { +namespace renderengine { +namespace gl { + +SortedVector GLExtensions::parseExtensionString(char const* extensions) { + SortedVector list; + + char const* curr = extensions; + char const* head = curr; + do { + head = strchr(curr, ' '); + String8 s(curr, head ? head - curr : strlen(curr)); + if (s.length()) { + list.add(s); + } + curr = head + 1; + } while (head); + + return list; +} + +void GLExtensions::initWithGLStrings(GLubyte const* vendor, GLubyte const* renderer, + GLubyte const* version, GLubyte const* extensions) { + mVendor = (char const*)vendor; + mRenderer = (char const*)renderer; + mVersion = (char const*)version; + mExtensions = (char const*)extensions; + mExtensionList = parseExtensionString(mExtensions); +} + +bool GLExtensions::hasExtension(char const* extension) const { + const String8 s(extension); + return mExtensionList.indexOf(s) >= 0; +} + +char const* GLExtensions::getVendor() const { + return mVendor.string(); +} + +char const* GLExtensions::getRenderer() const { + return mRenderer.string(); +} + +char const* GLExtensions::getVersion() const { + return mVersion.string(); +} + +char const* GLExtensions::getExtensions() const { + return mExtensions.string(); +} + +void GLExtensions::initWithEGLStrings(char const* eglVersion, char const* eglExtensions) { + mEGLVersion = eglVersion; + mEGLExtensions = eglExtensions; + mEGLExtensionList = parseExtensionString(mEGLExtensions); + + // EGL_ANDROIDX_no_config_context is an experimental extension with no + // written specification. It will be replaced by something more formal. + // SurfaceFlinger is using it to allow a single EGLContext to render to + // both a 16-bit primary display framebuffer and a 32-bit virtual display + // framebuffer. + // + // EGL_KHR_no_config_context is official extension to allow creating a + // context that works with any surface of a display. + if (hasEGLExtension("EGL_ANDROIDX_no_config_context") || + hasEGLExtension("EGL_KHR_no_config_context")) { + mHasNoConfigContext = true; + } + + if (hasEGLExtension("EGL_ANDROID_native_fence_sync")) { + mHasNativeFenceSync = true; + } + if (hasEGLExtension("EGL_KHR_fence_sync")) { + mHasFenceSync = true; + } + if (hasEGLExtension("EGL_KHR_wait_sync")) { + mHasWaitSync = true; + } + if (hasEGLExtension("EGL_EXT_protected_content")) { + mHasProtectedContent = true; + } + if (hasEGLExtension("EGL_IMG_context_priority")) { + mHasContextPriority = true; + } +} + +char const* GLExtensions::getEGLVersion() const { + return mEGLVersion.string(); +} + +char const* GLExtensions::getEGLExtensions() const { + return mEGLExtensions.string(); +} + +bool GLExtensions::hasEGLExtension(char const* extension) const { + const String8 s(extension); + return mEGLExtensionList.indexOf(s) >= 0; +} + +} // namespace gl +} // namespace renderengine +} // namespace android diff --git a/services/surfaceflinger/RenderEngine/gl/GLExtensions.h b/services/surfaceflinger/RenderEngine/gl/GLExtensions.h new file mode 100644 index 0000000000..efdd8b7ac2 --- /dev/null +++ b/services/surfaceflinger/RenderEngine/gl/GLExtensions.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2010 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. + */ + +#ifndef ANDROID_SF_GLEXTENSION_H +#define ANDROID_SF_GLEXTENSION_H + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace renderengine { +namespace gl { + +class GLExtensions : public Singleton { + friend class Singleton; + + bool mHasNoConfigContext = false; + bool mHasNativeFenceSync = false; + bool mHasFenceSync = false; + bool mHasWaitSync = false; + bool mHasProtectedContent = false; + bool mHasContextPriority = false; + + String8 mVendor; + String8 mRenderer; + String8 mVersion; + String8 mExtensions; + SortedVector mExtensionList; + + String8 mEGLVersion; + String8 mEGLExtensions; + SortedVector mEGLExtensionList; + + static SortedVector parseExtensionString(char const* extensions); + + GLExtensions(const GLExtensions&); + GLExtensions& operator=(const GLExtensions&); + +protected: + GLExtensions() = default; + +public: + bool hasNoConfigContext() const { return mHasNoConfigContext; } + bool hasNativeFenceSync() const { return mHasNativeFenceSync; } + bool hasFenceSync() const { return mHasFenceSync; } + bool hasWaitSync() const { return mHasWaitSync; } + bool hasProtectedContent() const { return mHasProtectedContent; } + bool hasContextPriority() const { return mHasContextPriority; } + + void initWithGLStrings(GLubyte const* vendor, GLubyte const* renderer, GLubyte const* version, + GLubyte const* extensions); + char const* getVendor() const; + char const* getRenderer() const; + char const* getVersion() const; + char const* getExtensions() const; + bool hasExtension(char const* extension) const; + + void initWithEGLStrings(char const* eglVersion, char const* eglExtensions); + char const* getEGLVersion() const; + char const* getEGLExtensions() const; + bool hasEGLExtension(char const* extension) const; +}; + +} // namespace gl +} // namespace renderengine +} // namespace android + +#endif // ANDROID_SF_GLEXTENSION_H diff --git a/services/surfaceflinger/RenderEngine/gl/Program.cpp b/services/surfaceflinger/RenderEngine/gl/Program.cpp new file mode 100644 index 0000000000..4d6839bfe3 --- /dev/null +++ b/services/surfaceflinger/RenderEngine/gl/Program.cpp @@ -0,0 +1,159 @@ +/*Gluint + * Copyright 2013 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. + */ + +#include "Program.h" + +#include + +#include +#include +#include +#include +#include "ProgramCache.h" + +namespace android { +namespace renderengine { +namespace gl { + +Program::Program(const ProgramCache::Key& /*needs*/, const char* vertex, const char* fragment) + : mInitialized(false) { + GLuint vertexId = buildShader(vertex, GL_VERTEX_SHADER); + GLuint fragmentId = buildShader(fragment, GL_FRAGMENT_SHADER); + GLuint programId = glCreateProgram(); + glAttachShader(programId, vertexId); + glAttachShader(programId, fragmentId); + glBindAttribLocation(programId, position, "position"); + glBindAttribLocation(programId, texCoords, "texCoords"); + glLinkProgram(programId); + + GLint status; + glGetProgramiv(programId, GL_LINK_STATUS, &status); + if (status != GL_TRUE) { + ALOGE("Error while linking shaders:"); + GLint infoLen = 0; + glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen > 1) { + GLchar log[infoLen]; + glGetProgramInfoLog(programId, infoLen, 0, &log[0]); + ALOGE("%s", log); + } + glDetachShader(programId, vertexId); + glDetachShader(programId, fragmentId); + glDeleteShader(vertexId); + glDeleteShader(fragmentId); + glDeleteProgram(programId); + } else { + mProgram = programId; + mVertexShader = vertexId; + mFragmentShader = fragmentId; + mInitialized = true; + mProjectionMatrixLoc = glGetUniformLocation(programId, "projection"); + mTextureMatrixLoc = glGetUniformLocation(programId, "texture"); + mSamplerLoc = glGetUniformLocation(programId, "sampler"); + mColorLoc = glGetUniformLocation(programId, "color"); + mDisplayMaxLuminanceLoc = glGetUniformLocation(programId, "displayMaxLuminance"); + mInputTransformMatrixLoc = glGetUniformLocation(programId, "inputTransformMatrix"); + mOutputTransformMatrixLoc = glGetUniformLocation(programId, "outputTransformMatrix"); + + // set-up the default values for our uniforms + glUseProgram(programId); + glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, mat4().asArray()); + glEnableVertexAttribArray(0); + } +} + +Program::~Program() {} + +bool Program::isValid() const { + return mInitialized; +} + +void Program::use() { + glUseProgram(mProgram); +} + +GLuint Program::getAttrib(const char* name) const { + // TODO: maybe use a local cache + return glGetAttribLocation(mProgram, name); +} + +GLint Program::getUniform(const char* name) const { + // TODO: maybe use a local cache + return glGetUniformLocation(mProgram, name); +} + +GLuint Program::buildShader(const char* source, GLenum type) { + GLuint shader = glCreateShader(type); + glShaderSource(shader, 1, &source, 0); + glCompileShader(shader); + GLint status; + glGetShaderiv(shader, GL_COMPILE_STATUS, &status); + if (status != GL_TRUE) { + // Some drivers return wrong values for GL_INFO_LOG_LENGTH + // use a fixed size instead + GLchar log[512]; + glGetShaderInfoLog(shader, sizeof(log), 0, log); + ALOGE("Error while compiling shader: \n%s\n%s", source, log); + glDeleteShader(shader); + return 0; + } + return shader; +} + +String8& Program::dumpShader(String8& result, GLenum /*type*/) { + GLuint shader = GL_FRAGMENT_SHADER ? mFragmentShader : mVertexShader; + GLint l; + glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &l); + char* src = new char[l]; + glGetShaderSource(shader, l, nullptr, src); + result.append(src); + delete[] src; + return result; +} + +void Program::setUniforms(const Description& desc) { + // TODO: we should have a mechanism here to not always reset uniforms that + // didn't change for this program. + + if (mSamplerLoc >= 0) { + glUniform1i(mSamplerLoc, 0); + glUniformMatrix4fv(mTextureMatrixLoc, 1, GL_FALSE, desc.mTexture.getMatrix().asArray()); + } + if (mColorLoc >= 0) { + const float color[4] = {desc.mColor.r, desc.mColor.g, desc.mColor.b, desc.mColor.a}; + glUniform4fv(mColorLoc, 1, color); + } + if (mInputTransformMatrixLoc >= 0) { + mat4 inputTransformMatrix = mat4(desc.mInputTransformMatrix); + glUniformMatrix4fv(mInputTransformMatrixLoc, 1, GL_FALSE, inputTransformMatrix.asArray()); + } + if (mOutputTransformMatrixLoc >= 0) { + // The output transform matrix and color matrix can be combined as one matrix + // that is applied right before applying OETF. + mat4 outputTransformMatrix = desc.mColorMatrix * desc.mOutputTransformMatrix; + glUniformMatrix4fv(mOutputTransformMatrixLoc, 1, GL_FALSE, + outputTransformMatrix.asArray()); + } + if (mDisplayMaxLuminanceLoc >= 0) { + glUniform1f(mDisplayMaxLuminanceLoc, desc.mDisplayMaxLuminance); + } + // these uniforms are always present + glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, desc.mProjectionMatrix.asArray()); +} + +} // namespace gl +} // namespace renderengine +} // namespace android diff --git a/services/surfaceflinger/RenderEngine/gl/Program.h b/services/surfaceflinger/RenderEngine/gl/Program.h new file mode 100644 index 0000000000..bb429efb43 --- /dev/null +++ b/services/surfaceflinger/RenderEngine/gl/Program.h @@ -0,0 +1,95 @@ +/* + * Copyright 2013 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. + */ + +#ifndef SF_RENDER_ENGINE_PROGRAM_H +#define SF_RENDER_ENGINE_PROGRAM_H + +#include + +#include +#include +#include "ProgramCache.h" + +namespace android { + +class String8; + +namespace renderengine { +namespace gl { + +/* + * Abstracts a GLSL program comprising a vertex and fragment shader + */ +class Program { +public: + // known locations for position and texture coordinates + enum { position = 0, texCoords = 1 }; + + Program(const ProgramCache::Key& needs, const char* vertex, const char* fragment); + ~Program(); + + /* whether this object is usable */ + bool isValid() const; + + /* Binds this program to the GLES context */ + void use(); + + /* Returns the location of the specified attribute */ + GLuint getAttrib(const char* name) const; + + /* Returns the location of the specified uniform */ + GLint getUniform(const char* name) const; + + /* set-up uniforms from the description */ + void setUniforms(const Description& desc); + +private: + GLuint buildShader(const char* source, GLenum type); + String8& dumpShader(String8& result, GLenum type); + + // whether the initialization succeeded + bool mInitialized; + + // Name of the OpenGL program and shaders + GLuint mProgram; + GLuint mVertexShader; + GLuint mFragmentShader; + + /* location of the projection matrix uniform */ + GLint mProjectionMatrixLoc; + + /* location of the texture matrix uniform */ + GLint mTextureMatrixLoc; + + /* location of the sampler uniform */ + GLint mSamplerLoc; + + /* location of the color uniform */ + GLint mColorLoc; + + /* location of display luminance uniform */ + GLint mDisplayMaxLuminanceLoc; + + /* location of transform matrix */ + GLint mInputTransformMatrixLoc; + GLint mOutputTransformMatrixLoc; +}; + +} // namespace gl +} // namespace renderengine +} // namespace android + +#endif /* SF_RENDER_ENGINE_PROGRAM_H */ diff --git a/services/surfaceflinger/RenderEngine/gl/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/gl/ProgramCache.cpp new file mode 100644 index 0000000000..a19c1f1dcc --- /dev/null +++ b/services/surfaceflinger/RenderEngine/gl/ProgramCache.cpp @@ -0,0 +1,689 @@ +/* + * Copyright 2013 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 ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "ProgramCache.h" + +#include +#include +#include +#include +#include +#include "Program.h" + +ANDROID_SINGLETON_STATIC_INSTANCE(android::renderengine::gl::ProgramCache) + +namespace android { +namespace renderengine { +namespace gl { + +/* + * A simple formatter class to automatically add the endl and + * manage the indentation. + */ + +class Formatter; +static Formatter& indent(Formatter& f); +static Formatter& dedent(Formatter& f); + +class Formatter { + String8 mString; + int mIndent; + typedef Formatter& (*FormaterManipFunc)(Formatter&); + friend Formatter& indent(Formatter& f); + friend Formatter& dedent(Formatter& f); + +public: + Formatter() : mIndent(0) {} + + String8 getString() const { return mString; } + + friend Formatter& operator<<(Formatter& out, const char* in) { + for (int i = 0; i < out.mIndent; i++) { + out.mString.append(" "); + } + out.mString.append(in); + out.mString.append("\n"); + return out; + } + friend inline Formatter& operator<<(Formatter& out, const String8& in) { + return operator<<(out, in.string()); + } + friend inline Formatter& operator<<(Formatter& to, FormaterManipFunc func) { + return (*func)(to); + } +}; +Formatter& indent(Formatter& f) { + f.mIndent++; + return f; +} +Formatter& dedent(Formatter& f) { + f.mIndent--; + return f; +} + +ProgramCache::ProgramCache() {} + +ProgramCache::~ProgramCache() {} + +void ProgramCache::primeCache(bool useColorManagement) { + uint32_t shaderCount = 0; + uint32_t keyMask = Key::BLEND_MASK | Key::OPACITY_MASK | Key::ALPHA_MASK | Key::TEXTURE_MASK; + // Prime the cache for all combinations of the above masks, + // leaving off the experimental color matrix mask options. + + nsecs_t timeBefore = systemTime(); + for (uint32_t keyVal = 0; keyVal <= keyMask; keyVal++) { + Key shaderKey; + shaderKey.set(keyMask, keyVal); + uint32_t tex = shaderKey.getTextureTarget(); + if (tex != Key::TEXTURE_OFF && tex != Key::TEXTURE_EXT && tex != Key::TEXTURE_2D) { + continue; + } + Program* program = mCache.valueFor(shaderKey); + if (program == nullptr) { + program = generateProgram(shaderKey); + mCache.add(shaderKey, program); + shaderCount++; + } + } + + // Prime for sRGB->P3 conversion + if (useColorManagement) { + Key shaderKey; + shaderKey.set(Key::BLEND_MASK | Key::TEXTURE_MASK | Key::OUTPUT_TRANSFORM_MATRIX_MASK | + Key::INPUT_TF_MASK | Key::OUTPUT_TF_MASK, + Key::BLEND_PREMULT | Key::TEXTURE_EXT | Key::OUTPUT_TRANSFORM_MATRIX_ON | + Key::INPUT_TF_SRGB | Key::OUTPUT_TF_SRGB); + for (int i = 0; i < 4; i++) { + shaderKey.set(Key::OPACITY_MASK, + (i & 1) ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT); + shaderKey.set(Key::ALPHA_MASK, (i & 2) ? Key::ALPHA_LT_ONE : Key::ALPHA_EQ_ONE); + Program* program = mCache.valueFor(shaderKey); + if (program == nullptr) { + program = generateProgram(shaderKey); + mCache.add(shaderKey, program); + shaderCount++; + } + } + } + + nsecs_t timeAfter = systemTime(); + float compileTimeMs = static_cast(timeAfter - timeBefore) / 1.0E6; + ALOGD("shader cache generated - %u shaders in %f ms\n", shaderCount, compileTimeMs); +} + +ProgramCache::Key ProgramCache::computeKey(const Description& description) { + Key needs; + needs.set(Key::TEXTURE_MASK, + !description.mTextureEnabled + ? Key::TEXTURE_OFF + : description.mTexture.getTextureTarget() == GL_TEXTURE_EXTERNAL_OES + ? Key::TEXTURE_EXT + : description.mTexture.getTextureTarget() == GL_TEXTURE_2D + ? Key::TEXTURE_2D + : Key::TEXTURE_OFF) + .set(Key::ALPHA_MASK, + (description.mColor.a < 1) ? Key::ALPHA_LT_ONE : Key::ALPHA_EQ_ONE) + .set(Key::BLEND_MASK, + description.mPremultipliedAlpha ? Key::BLEND_PREMULT : Key::BLEND_NORMAL) + .set(Key::OPACITY_MASK, + description.mOpaque ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT) + .set(Key::Key::INPUT_TRANSFORM_MATRIX_MASK, + description.hasInputTransformMatrix() ? + Key::INPUT_TRANSFORM_MATRIX_ON : Key::INPUT_TRANSFORM_MATRIX_OFF) + .set(Key::Key::OUTPUT_TRANSFORM_MATRIX_MASK, + description.hasOutputTransformMatrix() || description.hasColorMatrix() ? + Key::OUTPUT_TRANSFORM_MATRIX_ON : Key::OUTPUT_TRANSFORM_MATRIX_OFF); + + needs.set(Key::Y410_BT2020_MASK, + description.mY410BT2020 ? Key::Y410_BT2020_ON : Key::Y410_BT2020_OFF); + + if (needs.hasTransformMatrix() || (needs.getInputTF() != needs.getOutputTF())) { + switch (description.mInputTransferFunction) { + case Description::TransferFunction::LINEAR: + default: + needs.set(Key::INPUT_TF_MASK, Key::INPUT_TF_LINEAR); + break; + case Description::TransferFunction::SRGB: + needs.set(Key::INPUT_TF_MASK, Key::INPUT_TF_SRGB); + break; + case Description::TransferFunction::ST2084: + needs.set(Key::INPUT_TF_MASK, Key::INPUT_TF_ST2084); + break; + case Description::TransferFunction::HLG: + needs.set(Key::INPUT_TF_MASK, Key::INPUT_TF_HLG); + break; + } + + switch (description.mOutputTransferFunction) { + case Description::TransferFunction::LINEAR: + default: + needs.set(Key::OUTPUT_TF_MASK, Key::OUTPUT_TF_LINEAR); + break; + case Description::TransferFunction::SRGB: + needs.set(Key::OUTPUT_TF_MASK, Key::OUTPUT_TF_SRGB); + break; + case Description::TransferFunction::ST2084: + needs.set(Key::OUTPUT_TF_MASK, Key::OUTPUT_TF_ST2084); + break; + case Description::TransferFunction::HLG: + needs.set(Key::OUTPUT_TF_MASK, Key::OUTPUT_TF_HLG); + break; + } + } + + return needs; +} + +// Generate EOTF that converts signal values to relative display light, +// both normalized to [0, 1]. +void ProgramCache::generateEOTF(Formatter& fs, const Key& needs) { + switch (needs.getInputTF()) { + case Key::INPUT_TF_SRGB: + fs << R"__SHADER__( + float EOTF_sRGB(float srgb) { + return srgb <= 0.04045 ? srgb / 12.92 : pow((srgb + 0.055) / 1.055, 2.4); + } + + vec3 EOTF_sRGB(const vec3 srgb) { + return vec3(EOTF_sRGB(srgb.r), EOTF_sRGB(srgb.g), EOTF_sRGB(srgb.b)); + } + + vec3 EOTF(const vec3 srgb) { + return sign(srgb.rgb) * EOTF_sRGB(abs(srgb.rgb)); + } + )__SHADER__"; + break; + case Key::INPUT_TF_ST2084: + fs << R"__SHADER__( + vec3 EOTF(const highp vec3 color) { + const highp float m1 = (2610.0 / 4096.0) / 4.0; + const highp float m2 = (2523.0 / 4096.0) * 128.0; + const highp float c1 = (3424.0 / 4096.0); + const highp float c2 = (2413.0 / 4096.0) * 32.0; + const highp float c3 = (2392.0 / 4096.0) * 32.0; + + highp vec3 tmp = pow(color, 1.0 / vec3(m2)); + tmp = max(tmp - c1, 0.0) / (c2 - c3 * tmp); + return pow(tmp, 1.0 / vec3(m1)); + } + )__SHADER__"; + break; + case Key::INPUT_TF_HLG: + fs << R"__SHADER__( + highp float EOTF_channel(const highp float channel) { + const highp float a = 0.17883277; + const highp float b = 0.28466892; + const highp float c = 0.55991073; + return channel <= 0.5 ? channel * channel / 3.0 : + (exp((channel - c) / a) + b) / 12.0; + } + + vec3 EOTF(const highp vec3 color) { + return vec3(EOTF_channel(color.r), EOTF_channel(color.g), + EOTF_channel(color.b)); + } + )__SHADER__"; + break; + default: + fs << R"__SHADER__( + vec3 EOTF(const vec3 linear) { + return linear; + } + )__SHADER__"; + break; + } +} + +void ProgramCache::generateToneMappingProcess(Formatter& fs, const Key& needs) { + // Convert relative light to absolute light. + switch (needs.getInputTF()) { + case Key::INPUT_TF_ST2084: + fs << R"__SHADER__( + highp vec3 ScaleLuminance(highp vec3 color) { + return color * 10000.0; + } + )__SHADER__"; + break; + case Key::INPUT_TF_HLG: + fs << R"__SHADER__( + highp vec3 ScaleLuminance(highp vec3 color) { + // The formula is: + // alpha * pow(Y, gamma - 1.0) * color + beta; + // where alpha is 1000.0, gamma is 1.2, beta is 0.0. + return color * 1000.0 * pow(color.y, 0.2); + } + )__SHADER__"; + break; + default: + fs << R"__SHADER__( + highp vec3 ScaleLuminance(highp vec3 color) { + return color * displayMaxLuminance; + } + )__SHADER__"; + break; + } + + // Tone map absolute light to display luminance range. + switch (needs.getInputTF()) { + case Key::INPUT_TF_ST2084: + case Key::INPUT_TF_HLG: + switch (needs.getOutputTF()) { + case Key::OUTPUT_TF_HLG: + // Right now when mixed PQ and HLG contents are presented, + // HLG content will always be converted to PQ. However, for + // completeness, we simply clamp the value to [0.0, 1000.0]. + fs << R"__SHADER__( + highp vec3 ToneMap(highp vec3 color) { + return clamp(color, 0.0, 1000.0); + } + )__SHADER__"; + break; + case Key::OUTPUT_TF_ST2084: + fs << R"__SHADER__( + highp vec3 ToneMap(highp vec3 color) { + return color; + } + )__SHADER__"; + break; + default: + fs << R"__SHADER__( + highp vec3 ToneMap(highp vec3 color) { + const float maxMasteringLumi = 1000.0; + const float maxContentLumi = 1000.0; + const float maxInLumi = min(maxMasteringLumi, maxContentLumi); + float maxOutLumi = displayMaxLuminance; + + float nits = color.y; + + // clamp to max input luminance + nits = clamp(nits, 0.0, maxInLumi); + + // scale [0.0, maxInLumi] to [0.0, maxOutLumi] + if (maxInLumi <= maxOutLumi) { + nits *= maxOutLumi / maxInLumi; + } else { + // three control points + const float x0 = 10.0; + const float y0 = 17.0; + float x1 = maxOutLumi * 0.75; + float y1 = x1; + float x2 = x1 + (maxInLumi - x1) / 2.0; + float y2 = y1 + (maxOutLumi - y1) * 0.75; + + // horizontal distances between the last three control points + float h12 = x2 - x1; + float h23 = maxInLumi - x2; + // tangents at the last three control points + float m1 = (y2 - y1) / h12; + float m3 = (maxOutLumi - y2) / h23; + float m2 = (m1 + m3) / 2.0; + + if (nits < x0) { + // scale [0.0, x0] to [0.0, y0] linearly + float slope = y0 / x0; + nits *= slope; + } else if (nits < x1) { + // scale [x0, x1] to [y0, y1] linearly + float slope = (y1 - y0) / (x1 - x0); + nits = y0 + (nits - x0) * slope; + } else if (nits < x2) { + // scale [x1, x2] to [y1, y2] using Hermite interp + float t = (nits - x1) / h12; + nits = (y1 * (1.0 + 2.0 * t) + h12 * m1 * t) * (1.0 - t) * (1.0 - t) + + (y2 * (3.0 - 2.0 * t) + h12 * m2 * (t - 1.0)) * t * t; + } else { + // scale [x2, maxInLumi] to [y2, maxOutLumi] using Hermite interp + float t = (nits - x2) / h23; + nits = (y2 * (1.0 + 2.0 * t) + h23 * m2 * t) * (1.0 - t) * (1.0 - t) + + (maxOutLumi * (3.0 - 2.0 * t) + h23 * m3 * (t - 1.0)) * t * t; + } + } + + return color * (nits / max(1e-6, color.y)); + } + )__SHADER__"; + break; + } + break; + default: + // inverse tone map; the output luminance can be up to maxOutLumi. + fs << R"__SHADER__( + highp vec3 ToneMap(highp vec3 color) { + const float maxOutLumi = 3000.0; + + const float x0 = 5.0; + const float y0 = 2.5; + float x1 = displayMaxLuminance * 0.7; + float y1 = maxOutLumi * 0.15; + float x2 = displayMaxLuminance * 0.9; + float y2 = maxOutLumi * 0.45; + float x3 = displayMaxLuminance; + float y3 = maxOutLumi; + + float c1 = y1 / 3.0; + float c2 = y2 / 2.0; + float c3 = y3 / 1.5; + + float nits = color.y; + + float scale; + if (nits <= x0) { + // scale [0.0, x0] to [0.0, y0] linearly + const float slope = y0 / x0; + nits *= slope; + } else if (nits <= x1) { + // scale [x0, x1] to [y0, y1] using a curve + float t = (nits - x0) / (x1 - x0); + nits = (1.0 - t) * (1.0 - t) * y0 + 2.0 * (1.0 - t) * t * c1 + t * t * y1; + } else if (nits <= x2) { + // scale [x1, x2] to [y1, y2] using a curve + float t = (nits - x1) / (x2 - x1); + nits = (1.0 - t) * (1.0 - t) * y1 + 2.0 * (1.0 - t) * t * c2 + t * t * y2; + } else { + // scale [x2, x3] to [y2, y3] using a curve + float t = (nits - x2) / (x3 - x2); + nits = (1.0 - t) * (1.0 - t) * y2 + 2.0 * (1.0 - t) * t * c3 + t * t * y3; + } + + return color * (nits / max(1e-6, color.y)); + } + )__SHADER__"; + break; + } + + // convert absolute light to relative light. + switch (needs.getOutputTF()) { + case Key::OUTPUT_TF_ST2084: + fs << R"__SHADER__( + highp vec3 NormalizeLuminance(highp vec3 color) { + return color / 10000.0; + } + )__SHADER__"; + break; + case Key::OUTPUT_TF_HLG: + fs << R"__SHADER__( + highp vec3 NormalizeLuminance(highp vec3 color) { + return color / 1000.0 * pow(color.y / 1000.0, -0.2 / 1.2); + } + )__SHADER__"; + break; + default: + fs << R"__SHADER__( + highp vec3 NormalizeLuminance(highp vec3 color) { + return color / displayMaxLuminance; + } + )__SHADER__"; + break; + } +} + +// Generate OOTF that modifies the relative scence light to relative display light. +void ProgramCache::generateOOTF(Formatter& fs, const ProgramCache::Key& needs) { + if (!needs.needsToneMapping()) { + fs << R"__SHADER__( + highp vec3 OOTF(const highp vec3 color) { + return color; + } + )__SHADER__"; + } else { + generateToneMappingProcess(fs, needs); + fs << R"__SHADER__( + highp vec3 OOTF(const highp vec3 color) { + return NormalizeLuminance(ToneMap(ScaleLuminance(color))); + } + )__SHADER__"; + } +} + +// Generate OETF that converts relative display light to signal values, +// both normalized to [0, 1] +void ProgramCache::generateOETF(Formatter& fs, const Key& needs) { + switch (needs.getOutputTF()) { + case Key::OUTPUT_TF_SRGB: + fs << R"__SHADER__( + float OETF_sRGB(const float linear) { + return linear <= 0.0031308 ? + linear * 12.92 : (pow(linear, 1.0 / 2.4) * 1.055) - 0.055; + } + + vec3 OETF_sRGB(const vec3 linear) { + return vec3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b)); + } + + vec3 OETF(const vec3 linear) { + return sign(linear.rgb) * OETF_sRGB(abs(linear.rgb)); + } + )__SHADER__"; + break; + case Key::OUTPUT_TF_ST2084: + fs << R"__SHADER__( + vec3 OETF(const vec3 linear) { + const highp float m1 = (2610.0 / 4096.0) / 4.0; + const highp float m2 = (2523.0 / 4096.0) * 128.0; + const highp float c1 = (3424.0 / 4096.0); + const highp float c2 = (2413.0 / 4096.0) * 32.0; + const highp float c3 = (2392.0 / 4096.0) * 32.0; + + highp vec3 tmp = pow(linear, vec3(m1)); + tmp = (c1 + c2 * tmp) / (1.0 + c3 * tmp); + return pow(tmp, vec3(m2)); + } + )__SHADER__"; + break; + case Key::OUTPUT_TF_HLG: + fs << R"__SHADER__( + highp float OETF_channel(const highp float channel) { + const highp float a = 0.17883277; + const highp float b = 0.28466892; + const highp float c = 0.55991073; + return channel <= 1.0 / 12.0 ? sqrt(3.0 * channel) : + a * log(12.0 * channel - b) + c; + } + + vec3 OETF(const highp vec3 color) { + return vec3(OETF_channel(color.r), OETF_channel(color.g), + OETF_channel(color.b)); + } + )__SHADER__"; + break; + default: + fs << R"__SHADER__( + vec3 OETF(const vec3 linear) { + return linear; + } + )__SHADER__"; + break; + } +} + +String8 ProgramCache::generateVertexShader(const Key& needs) { + Formatter vs; + if (needs.isTexturing()) { + vs << "attribute vec4 texCoords;" + << "varying vec2 outTexCoords;"; + } + vs << "attribute vec4 position;" + << "uniform mat4 projection;" + << "uniform mat4 texture;" + << "void main(void) {" << indent << "gl_Position = projection * position;"; + if (needs.isTexturing()) { + vs << "outTexCoords = (texture * texCoords).st;"; + } + vs << dedent << "}"; + return vs.getString(); +} + +String8 ProgramCache::generateFragmentShader(const Key& needs) { + Formatter fs; + if (needs.getTextureTarget() == Key::TEXTURE_EXT) { + fs << "#extension GL_OES_EGL_image_external : require"; + } + + // default precision is required-ish in fragment shaders + fs << "precision mediump float;"; + + if (needs.getTextureTarget() == Key::TEXTURE_EXT) { + fs << "uniform samplerExternalOES sampler;" + << "varying vec2 outTexCoords;"; + } else if (needs.getTextureTarget() == Key::TEXTURE_2D) { + fs << "uniform sampler2D sampler;" + << "varying vec2 outTexCoords;"; + } + + if (needs.getTextureTarget() == Key::TEXTURE_OFF || needs.hasAlpha()) { + fs << "uniform vec4 color;"; + } + + if (needs.isY410BT2020()) { + fs << R"__SHADER__( + vec3 convertY410BT2020(const vec3 color) { + const vec3 offset = vec3(0.0625, 0.5, 0.5); + const mat3 transform = mat3( + vec3(1.1678, 1.1678, 1.1678), + vec3( 0.0, -0.1878, 2.1481), + vec3(1.6836, -0.6523, 0.0)); + // Y is in G, U is in R, and V is in B + return clamp(transform * (color.grb - offset), 0.0, 1.0); + } + )__SHADER__"; + } + + if (needs.hasTransformMatrix() || (needs.getInputTF() != needs.getOutputTF())) { + // Currently, display maximum luminance is needed when doing tone mapping. + if (needs.needsToneMapping()) { + fs << "uniform float displayMaxLuminance;"; + } + + if (needs.hasInputTransformMatrix()) { + fs << "uniform mat4 inputTransformMatrix;"; + fs << R"__SHADER__( + highp vec3 InputTransform(const highp vec3 color) { + return vec3(inputTransformMatrix * vec4(color, 1.0)); + } + )__SHADER__"; + } else { + fs << R"__SHADER__( + highp vec3 InputTransform(const highp vec3 color) { + return color; + } + )__SHADER__"; + } + + // the transformation from a wider colorspace to a narrower one can + // result in >1.0 or <0.0 pixel values + if (needs.hasOutputTransformMatrix()) { + fs << "uniform mat4 outputTransformMatrix;"; + fs << R"__SHADER__( + highp vec3 OutputTransform(const highp vec3 color) { + return clamp(vec3(outputTransformMatrix * vec4(color, 1.0)), 0.0, 1.0); + } + )__SHADER__"; + } else { + fs << R"__SHADER__( + highp vec3 OutputTransform(const highp vec3 color) { + return clamp(color, 0.0, 1.0); + } + )__SHADER__"; + } + + generateEOTF(fs, needs); + generateOOTF(fs, needs); + generateOETF(fs, needs); + } + + fs << "void main(void) {" << indent; + if (needs.isTexturing()) { + fs << "gl_FragColor = texture2D(sampler, outTexCoords);"; + if (needs.isY410BT2020()) { + fs << "gl_FragColor.rgb = convertY410BT2020(gl_FragColor.rgb);"; + } + } else { + fs << "gl_FragColor.rgb = color.rgb;"; + fs << "gl_FragColor.a = 1.0;"; + } + if (needs.isOpaque()) { + fs << "gl_FragColor.a = 1.0;"; + } + if (needs.hasAlpha()) { + // modulate the current alpha value with alpha set + if (needs.isPremultiplied()) { + // ... and the color too if we're premultiplied + fs << "gl_FragColor *= color.a;"; + } else { + fs << "gl_FragColor.a *= color.a;"; + } + } + + if (needs.hasTransformMatrix() || (needs.getInputTF() != needs.getOutputTF())) { + if (!needs.isOpaque() && needs.isPremultiplied()) { + // un-premultiply if needed before linearization + // avoid divide by 0 by adding 0.5/256 to the alpha channel + fs << "gl_FragColor.rgb = gl_FragColor.rgb / (gl_FragColor.a + 0.0019);"; + } + fs << "gl_FragColor.rgb = OETF(OutputTransform(OOTF(InputTransform(EOTF(gl_FragColor.rgb)))));"; + if (!needs.isOpaque() && needs.isPremultiplied()) { + // and re-premultiply if needed after gamma correction + fs << "gl_FragColor.rgb = gl_FragColor.rgb * (gl_FragColor.a + 0.0019);"; + } + } + + fs << dedent << "}"; + return fs.getString(); +} + +Program* ProgramCache::generateProgram(const Key& needs) { + ATRACE_CALL(); + + // vertex shader + String8 vs = generateVertexShader(needs); + + // fragment shader + String8 fs = generateFragmentShader(needs); + + Program* program = new Program(needs, vs.string(), fs.string()); + return program; +} + +void ProgramCache::useProgram(const Description& description) { + // generate the key for the shader based on the description + Key needs(computeKey(description)); + + // look-up the program in the cache + Program* program = mCache.valueFor(needs); + if (program == nullptr) { + // we didn't find our program, so generate one... + nsecs_t time = -systemTime(); + program = generateProgram(needs); + mCache.add(needs, program); + time += systemTime(); + + ALOGV(">>> generated new program: needs=%08X, time=%u ms (%zu programs)", needs.mKey, + uint32_t(ns2ms(time)), mCache.size()); + } + + // here we have a suitable program for this description + if (program->isValid()) { + program->use(); + program->setUniforms(description); + } +} + +} // namespace gl +} // namespace renderengine +} // namespace android diff --git a/services/surfaceflinger/RenderEngine/gl/ProgramCache.h b/services/surfaceflinger/RenderEngine/gl/ProgramCache.h new file mode 100644 index 0000000000..ea77a2d278 --- /dev/null +++ b/services/surfaceflinger/RenderEngine/gl/ProgramCache.h @@ -0,0 +1,204 @@ +/* + * Copyright 2013 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. + */ + +#ifndef SF_RENDER_ENGINE_PROGRAMCACHE_H +#define SF_RENDER_ENGINE_PROGRAMCACHE_H + +#include +#include +#include +#include +#include + +namespace android { + +class String8; + +namespace renderengine { + +class Description; + +namespace gl { + +class Formatter; +class Program; + +/* + * This class generates GLSL programs suitable to handle a given + * Description. It's responsible for figuring out what to + * generate from a Description. + * It also maintains a cache of these Programs. + */ +class ProgramCache : public Singleton { +public: + /* + * Key is used to retrieve a Program in the cache. + * A Key is generated from a Description. + */ + class Key { + friend class ProgramCache; + typedef uint32_t key_t; + key_t mKey; + + public: + enum { + BLEND_SHIFT = 0, + BLEND_MASK = 1 << BLEND_SHIFT, + BLEND_PREMULT = 1 << BLEND_SHIFT, + BLEND_NORMAL = 0 << BLEND_SHIFT, + + OPACITY_SHIFT = 1, + OPACITY_MASK = 1 << OPACITY_SHIFT, + OPACITY_OPAQUE = 1 << OPACITY_SHIFT, + OPACITY_TRANSLUCENT = 0 << OPACITY_SHIFT, + + ALPHA_SHIFT = 2, + ALPHA_MASK = 1 << ALPHA_SHIFT, + ALPHA_LT_ONE = 1 << ALPHA_SHIFT, + ALPHA_EQ_ONE = 0 << ALPHA_SHIFT, + + TEXTURE_SHIFT = 3, + TEXTURE_MASK = 3 << TEXTURE_SHIFT, + TEXTURE_OFF = 0 << TEXTURE_SHIFT, + TEXTURE_EXT = 1 << TEXTURE_SHIFT, + TEXTURE_2D = 2 << TEXTURE_SHIFT, + + INPUT_TRANSFORM_MATRIX_SHIFT = 5, + INPUT_TRANSFORM_MATRIX_MASK = 1 << INPUT_TRANSFORM_MATRIX_SHIFT, + INPUT_TRANSFORM_MATRIX_OFF = 0 << INPUT_TRANSFORM_MATRIX_SHIFT, + INPUT_TRANSFORM_MATRIX_ON = 1 << INPUT_TRANSFORM_MATRIX_SHIFT, + + OUTPUT_TRANSFORM_MATRIX_SHIFT = 6, + OUTPUT_TRANSFORM_MATRIX_MASK = 1 << OUTPUT_TRANSFORM_MATRIX_SHIFT, + OUTPUT_TRANSFORM_MATRIX_OFF = 0 << OUTPUT_TRANSFORM_MATRIX_SHIFT, + OUTPUT_TRANSFORM_MATRIX_ON = 1 << OUTPUT_TRANSFORM_MATRIX_SHIFT, + + INPUT_TF_SHIFT = 7, + INPUT_TF_MASK = 3 << INPUT_TF_SHIFT, + INPUT_TF_LINEAR = 0 << INPUT_TF_SHIFT, + INPUT_TF_SRGB = 1 << INPUT_TF_SHIFT, + INPUT_TF_ST2084 = 2 << INPUT_TF_SHIFT, + INPUT_TF_HLG = 3 << INPUT_TF_SHIFT, + + OUTPUT_TF_SHIFT = 9, + OUTPUT_TF_MASK = 3 << OUTPUT_TF_SHIFT, + OUTPUT_TF_LINEAR = 0 << OUTPUT_TF_SHIFT, + OUTPUT_TF_SRGB = 1 << OUTPUT_TF_SHIFT, + OUTPUT_TF_ST2084 = 2 << OUTPUT_TF_SHIFT, + OUTPUT_TF_HLG = 3 << OUTPUT_TF_SHIFT, + + Y410_BT2020_SHIFT = 11, + Y410_BT2020_MASK = 1 << Y410_BT2020_SHIFT, + Y410_BT2020_OFF = 0 << Y410_BT2020_SHIFT, + Y410_BT2020_ON = 1 << Y410_BT2020_SHIFT, + }; + + inline Key() : mKey(0) {} + inline Key(const Key& rhs) : mKey(rhs.mKey) {} + + inline Key& set(key_t mask, key_t value) { + mKey = (mKey & ~mask) | value; + return *this; + } + + inline bool isTexturing() const { return (mKey & TEXTURE_MASK) != TEXTURE_OFF; } + inline int getTextureTarget() const { return (mKey & TEXTURE_MASK); } + inline bool isPremultiplied() const { return (mKey & BLEND_MASK) == BLEND_PREMULT; } + inline bool isOpaque() const { return (mKey & OPACITY_MASK) == OPACITY_OPAQUE; } + inline bool hasAlpha() const { return (mKey & ALPHA_MASK) == ALPHA_LT_ONE; } + inline bool hasInputTransformMatrix() const { + return (mKey & INPUT_TRANSFORM_MATRIX_MASK) == INPUT_TRANSFORM_MATRIX_ON; + } + inline bool hasOutputTransformMatrix() const { + return (mKey & OUTPUT_TRANSFORM_MATRIX_MASK) == OUTPUT_TRANSFORM_MATRIX_ON; + } + inline bool hasTransformMatrix() const { + return hasInputTransformMatrix() || hasOutputTransformMatrix(); + } + inline int getInputTF() const { return (mKey & INPUT_TF_MASK); } + inline int getOutputTF() const { return (mKey & OUTPUT_TF_MASK); } + + // When HDR and non-HDR contents are mixed, or different types of HDR contents are + // mixed, we will do a tone mapping process to tone map the input content to output + // content. Currently, the following conversions handled, they are: + // * SDR -> HLG + // * SDR -> PQ + // * HLG -> PQ + inline bool needsToneMapping() const { + int inputTF = getInputTF(); + int outputTF = getOutputTF(); + + // Return false when converting from SDR to SDR. + if (inputTF == Key::INPUT_TF_SRGB && outputTF == Key::OUTPUT_TF_LINEAR) { + return false; + } + if (inputTF == Key::INPUT_TF_LINEAR && outputTF == Key::OUTPUT_TF_SRGB) { + return false; + } + + inputTF >>= Key::INPUT_TF_SHIFT; + outputTF >>= Key::OUTPUT_TF_SHIFT; + return inputTF != outputTF; + } + inline bool isY410BT2020() const { return (mKey & Y410_BT2020_MASK) == Y410_BT2020_ON; } + + // this is the definition of a friend function -- not a method of class Needs + friend inline int strictly_order_type(const Key& lhs, const Key& rhs) { + return (lhs.mKey < rhs.mKey) ? 1 : 0; + } + }; + + ProgramCache(); + ~ProgramCache(); + + // Generate shaders to populate the cache + void primeCache(bool useColorManagement); + + // useProgram lookup a suitable program in the cache or generates one + // if none can be found. + void useProgram(const Description& description); + +private: + // compute a cache Key from a Description + static Key computeKey(const Description& description); + // Generate EOTF based from Key. + static void generateEOTF(Formatter& fs, const Key& needs); + // Generate necessary tone mapping methods for OOTF. + static void generateToneMappingProcess(Formatter& fs, const Key& needs); + // Generate OOTF based from Key. + static void generateOOTF(Formatter& fs, const Key& needs); + // Generate OETF based from Key. + static void generateOETF(Formatter& fs, const Key& needs); + // generates a program from the Key + static Program* generateProgram(const Key& needs); + // generates the vertex shader from the Key + static String8 generateVertexShader(const Key& needs); + // generates the fragment shader from the Key + static String8 generateFragmentShader(const Key& needs); + + // Key/Value map used for caching Programs. Currently the cache + // is never shrunk. + DefaultKeyedVector mCache; +}; + +} // namespace gl +} // namespace renderengine + +ANDROID_BASIC_TYPES_TRAITS(renderengine::gl::ProgramCache::Key) + +} // namespace android + +#endif /* SF_RENDER_ENGINE_PROGRAMCACHE_H */ diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/Description.h b/services/surfaceflinger/RenderEngine/include/renderengine/Description.h deleted file mode 100644 index 9bc7e1c39c..0000000000 --- a/services/surfaceflinger/RenderEngine/include/renderengine/Description.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2013 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. - */ - -#include -#include - -#ifndef SF_RENDER_ENGINE_DESCRIPTION_H_ -#define SF_RENDER_ENGINE_DESCRIPTION_H_ - -namespace android { - -class Program; - -/* - * This holds the state of the rendering engine. This class is used - * to generate a corresponding GLSL program and set the appropriate - * uniform. - * - * Program and ProgramCache are friends and access the state directly - */ -class Description { -public: - Description() = default; - ~Description() = default; - - void setPremultipliedAlpha(bool premultipliedAlpha); - void setOpaque(bool opaque); - void setTexture(const Texture& texture); - void disableTexture(); - void setColor(const half4& color); - void setProjectionMatrix(const mat4& mtx); - void setColorMatrix(const mat4& mtx); - void setInputTransformMatrix(const mat3& matrix); - void setOutputTransformMatrix(const mat4& matrix); - bool hasInputTransformMatrix() const; - bool hasOutputTransformMatrix() const; - bool hasColorMatrix() const; - const mat4& getColorMatrix() const; - - void setY410BT2020(bool enable); - - enum class TransferFunction : int { - LINEAR, - SRGB, - ST2084, - HLG, // Hybrid Log-Gamma for HDR. - }; - void setInputTransferFunction(TransferFunction transferFunction); - void setOutputTransferFunction(TransferFunction transferFunction); - void setDisplayMaxLuminance(const float maxLuminance); - -private: - friend class Program; - friend class ProgramCache; - - // whether textures are premultiplied - bool mPremultipliedAlpha = false; - // whether this layer is marked as opaque - bool mOpaque = true; - - // Texture this layer uses - Texture mTexture; - bool mTextureEnabled = false; - - // color used when texturing is disabled or when setting alpha. - half4 mColor; - - // true if the sampled pixel values are in Y410/BT2020 rather than RGBA - bool mY410BT2020 = false; - - // transfer functions for the input/output - TransferFunction mInputTransferFunction = TransferFunction::LINEAR; - TransferFunction mOutputTransferFunction = TransferFunction::LINEAR; - - float mDisplayMaxLuminance; - - // projection matrix - mat4 mProjectionMatrix; - mat4 mColorMatrix; - mat3 mInputTransformMatrix; - mat4 mOutputTransformMatrix; -}; - -} /* namespace android */ - -#endif /* SF_RENDER_ENGINE_DESCRIPTION_H_ */ diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/include/renderengine/GLES20RenderEngine.h deleted file mode 100644 index 0e9efdb8d5..0000000000 --- a/services/surfaceflinger/RenderEngine/include/renderengine/GLES20RenderEngine.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2013 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. - */ - -#ifndef SF_GLES20RENDERENGINE_H_ -#define SF_GLES20RENDERENGINE_H_ - -#include -#include - -#include -#include -#include -#include - -// --------------------------------------------------------------------------- -namespace android { -// --------------------------------------------------------------------------- - -class String8; -class Mesh; -class Texture; - -namespace RE { -namespace impl { - -class GLES20RenderEngine : public RenderEngine { - GLuint mProtectedTexName; - GLint mMaxViewportDims[2]; - GLint mMaxTextureSize; - GLuint mVpWidth; - GLuint mVpHeight; - - struct Group { - GLuint texture; - GLuint fbo; - GLuint width; - GLuint height; - mat4 colorTransform; - }; - - Description mState; - Vector mGroupStack; - - virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, - uint32_t* status); - virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName); - -public: - GLES20RenderEngine(uint32_t featureFlags); // See RenderEngine::FeatureFlag - virtual ~GLES20RenderEngine(); - -protected: - virtual void dump(String8& result); - virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, - bool yswap, ui::Transform::orientation_flags rotation); - virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture, - const half4& color) override; - - // Color management related functions and state - void setSourceY410BT2020(bool enable) override; - void setSourceDataSpace(ui::Dataspace source) override; - void setOutputDataSpace(ui::Dataspace dataspace) override; - void setDisplayMaxLuminance(const float maxLuminance) override; - - virtual void setupLayerTexturing(const Texture& texture); - virtual void setupLayerBlackedOut(); - virtual void setupFillWithColor(float r, float g, float b, float a); - virtual void setupColorTransform(const mat4& colorTransform); - virtual void disableTexturing(); - virtual void disableBlending(); - - virtual void drawMesh(const Mesh& mesh); - - virtual size_t getMaxTextureSize() const; - virtual size_t getMaxViewportDims() const; - - // Current dataspace of layer being rendered - ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN; - - // Current output dataspace of the render engine - ui::Dataspace mOutputDataSpace = ui::Dataspace::UNKNOWN; - - // Whether device supports color management, currently color management - // supports sRGB, DisplayP3 color spaces. - const bool mUseColorManagement = false; - mat4 mSrgbToDisplayP3; - mat4 mDisplayP3ToSrgb; - mat3 mSrgbToXyz; - mat3 mBt2020ToXyz; - mat3 mDisplayP3ToXyz; - mat4 mXyzToSrgb; - mat4 mXyzToDisplayP3; - mat4 mXyzToBt2020; - -private: - // A data space is considered HDR data space if it has BT2020 color space - // with PQ or HLG transfer function. - bool isHdrDataSpace(const ui::Dataspace dataSpace) const; - bool needsXYZTransformMatrix() const; -}; - -// --------------------------------------------------------------------------- -} // namespace impl -} // namespace RE -} // namespace android -// --------------------------------------------------------------------------- - -#endif /* SF_GLES20RENDERENGINE_H_ */ diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/GLExtensions.h b/services/surfaceflinger/RenderEngine/include/renderengine/GLExtensions.h deleted file mode 100644 index 1ff0d24a34..0000000000 --- a/services/surfaceflinger/RenderEngine/include/renderengine/GLExtensions.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2010 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. - */ - -#ifndef ANDROID_SF_GLEXTENSION_H -#define ANDROID_SF_GLEXTENSION_H - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -namespace android { -// --------------------------------------------------------------------------- - -class GLExtensions : public Singleton { - friend class Singleton; - - bool mHasNoConfigContext = false; - bool mHasNativeFenceSync = false; - bool mHasFenceSync = false; - bool mHasWaitSync = false; - bool mHasProtectedContent = false; - bool mHasContextPriority = false; - - String8 mVendor; - String8 mRenderer; - String8 mVersion; - String8 mExtensions; - SortedVector mExtensionList; - - String8 mEGLVersion; - String8 mEGLExtensions; - SortedVector mEGLExtensionList; - - static SortedVector parseExtensionString(char const* extensions); - - GLExtensions(const GLExtensions&); - GLExtensions& operator=(const GLExtensions&); - -protected: - GLExtensions() = default; - -public: - bool hasNoConfigContext() const { return mHasNoConfigContext; } - bool hasNativeFenceSync() const { return mHasNativeFenceSync; } - bool hasFenceSync() const { return mHasFenceSync; } - bool hasWaitSync() const { return mHasWaitSync; } - bool hasProtectedContent() const { return mHasProtectedContent; } - bool hasContextPriority() const { return mHasContextPriority; } - - void initWithGLStrings(GLubyte const* vendor, GLubyte const* renderer, GLubyte const* version, - GLubyte const* extensions); - char const* getVendor() const; - char const* getRenderer() const; - char const* getVersion() const; - char const* getExtensions() const; - bool hasExtension(char const* extension) const; - - void initWithEGLStrings(char const* eglVersion, char const* eglExtensions); - char const* getEGLVersion() const; - char const* getEGLExtensions() const; - bool hasEGLExtension(char const* extension) const; -}; - -// --------------------------------------------------------------------------- -}; // namespace android - -#endif // ANDROID_SF_GLEXTENSION_H diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/Image.h b/services/surfaceflinger/RenderEngine/include/renderengine/Image.h index c38fe0a2ff..9b34b68c72 100644 --- a/services/surfaceflinger/RenderEngine/include/renderengine/Image.h +++ b/services/surfaceflinger/RenderEngine/include/renderengine/Image.h @@ -24,7 +24,7 @@ struct ANativeWindowBuffer; namespace android { -namespace RE { +namespace renderengine { class Image { public: @@ -36,7 +36,7 @@ namespace impl { class RenderEngine; -class Image : public RE::Image { +class Image : public renderengine::Image { public: explicit Image(const RenderEngine& engine); ~Image() override; @@ -55,6 +55,6 @@ private: EGLImageKHR mEGLImage = EGL_NO_IMAGE_KHR; }; -} // namespace impl -} // namespace RE -} // namespace android +} // namespace impl +} // namespace renderengine +} // namespace android diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/Mesh.h b/services/surfaceflinger/RenderEngine/include/renderengine/Mesh.h index d0a9ac0c65..39ca2f7aa2 100644 --- a/services/surfaceflinger/RenderEngine/include/renderengine/Mesh.h +++ b/services/surfaceflinger/RenderEngine/include/renderengine/Mesh.h @@ -20,6 +20,7 @@ #include namespace android { +namespace renderengine { class Mesh { public: @@ -97,5 +98,6 @@ private: Primitive mPrimitive; }; -} /* namespace android */ +} // namespace renderengine +} // namespace android #endif /* SF_RENDER_ENGINE_MESH_H */ diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/Program.h b/services/surfaceflinger/RenderEngine/include/renderengine/Program.h deleted file mode 100644 index 5e621cbed3..0000000000 --- a/services/surfaceflinger/RenderEngine/include/renderengine/Program.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2013 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. - */ - -#ifndef SF_RENDER_ENGINE_PROGRAM_H -#define SF_RENDER_ENGINE_PROGRAM_H - -#include - -#include -#include -#include - -namespace android { - -class String8; - -/* - * Abstracts a GLSL program comprising a vertex and fragment shader - */ -class Program { -public: - // known locations for position and texture coordinates - enum { position = 0, texCoords = 1 }; - - Program(const ProgramCache::Key& needs, const char* vertex, const char* fragment); - ~Program(); - - /* whether this object is usable */ - bool isValid() const; - - /* Binds this program to the GLES context */ - void use(); - - /* Returns the location of the specified attribute */ - GLuint getAttrib(const char* name) const; - - /* Returns the location of the specified uniform */ - GLint getUniform(const char* name) const; - - /* set-up uniforms from the description */ - void setUniforms(const Description& desc); - -private: - GLuint buildShader(const char* source, GLenum type); - String8& dumpShader(String8& result, GLenum type); - - // whether the initialization succeeded - bool mInitialized; - - // Name of the OpenGL program and shaders - GLuint mProgram; - GLuint mVertexShader; - GLuint mFragmentShader; - - /* location of the projection matrix uniform */ - GLint mProjectionMatrixLoc; - - /* location of the texture matrix uniform */ - GLint mTextureMatrixLoc; - - /* location of the sampler uniform */ - GLint mSamplerLoc; - - /* location of the color uniform */ - GLint mColorLoc; - - /* location of display luminance uniform */ - GLint mDisplayMaxLuminanceLoc; - - /* location of transform matrix */ - GLint mInputTransformMatrixLoc; - GLint mOutputTransformMatrixLoc; -}; - -} /* namespace android */ - -#endif /* SF_RENDER_ENGINE_PROGRAM_H */ diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/ProgramCache.h b/services/surfaceflinger/RenderEngine/include/renderengine/ProgramCache.h deleted file mode 100644 index a5bee45335..0000000000 --- a/services/surfaceflinger/RenderEngine/include/renderengine/ProgramCache.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2013 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. - */ - -#ifndef SF_RENDER_ENGINE_PROGRAMCACHE_H -#define SF_RENDER_ENGINE_PROGRAMCACHE_H - -#include -#include -#include -#include -#include - -namespace android { - -class Description; -class Formatter; -class Program; -class String8; - -/* - * This class generates GLSL programs suitable to handle a given - * Description. It's responsible for figuring out what to - * generate from a Description. - * It also maintains a cache of these Programs. - */ -class ProgramCache : public Singleton { -public: - /* - * Key is used to retrieve a Program in the cache. - * A Key is generated from a Description. - */ - class Key { - friend class ProgramCache; - typedef uint32_t key_t; - key_t mKey; - - public: - enum { - BLEND_SHIFT = 0, - BLEND_MASK = 1 << BLEND_SHIFT, - BLEND_PREMULT = 1 << BLEND_SHIFT, - BLEND_NORMAL = 0 << BLEND_SHIFT, - - OPACITY_SHIFT = 1, - OPACITY_MASK = 1 << OPACITY_SHIFT, - OPACITY_OPAQUE = 1 << OPACITY_SHIFT, - OPACITY_TRANSLUCENT = 0 << OPACITY_SHIFT, - - ALPHA_SHIFT = 2, - ALPHA_MASK = 1 << ALPHA_SHIFT, - ALPHA_LT_ONE = 1 << ALPHA_SHIFT, - ALPHA_EQ_ONE = 0 << ALPHA_SHIFT, - - TEXTURE_SHIFT = 3, - TEXTURE_MASK = 3 << TEXTURE_SHIFT, - TEXTURE_OFF = 0 << TEXTURE_SHIFT, - TEXTURE_EXT = 1 << TEXTURE_SHIFT, - TEXTURE_2D = 2 << TEXTURE_SHIFT, - - INPUT_TRANSFORM_MATRIX_SHIFT = 5, - INPUT_TRANSFORM_MATRIX_MASK = 1 << INPUT_TRANSFORM_MATRIX_SHIFT, - INPUT_TRANSFORM_MATRIX_OFF = 0 << INPUT_TRANSFORM_MATRIX_SHIFT, - INPUT_TRANSFORM_MATRIX_ON = 1 << INPUT_TRANSFORM_MATRIX_SHIFT, - - OUTPUT_TRANSFORM_MATRIX_SHIFT = 6, - OUTPUT_TRANSFORM_MATRIX_MASK = 1 << OUTPUT_TRANSFORM_MATRIX_SHIFT, - OUTPUT_TRANSFORM_MATRIX_OFF = 0 << OUTPUT_TRANSFORM_MATRIX_SHIFT, - OUTPUT_TRANSFORM_MATRIX_ON = 1 << OUTPUT_TRANSFORM_MATRIX_SHIFT, - - INPUT_TF_SHIFT = 7, - INPUT_TF_MASK = 3 << INPUT_TF_SHIFT, - INPUT_TF_LINEAR = 0 << INPUT_TF_SHIFT, - INPUT_TF_SRGB = 1 << INPUT_TF_SHIFT, - INPUT_TF_ST2084 = 2 << INPUT_TF_SHIFT, - INPUT_TF_HLG = 3 << INPUT_TF_SHIFT, - - OUTPUT_TF_SHIFT = 9, - OUTPUT_TF_MASK = 3 << OUTPUT_TF_SHIFT, - OUTPUT_TF_LINEAR = 0 << OUTPUT_TF_SHIFT, - OUTPUT_TF_SRGB = 1 << OUTPUT_TF_SHIFT, - OUTPUT_TF_ST2084 = 2 << OUTPUT_TF_SHIFT, - OUTPUT_TF_HLG = 3 << OUTPUT_TF_SHIFT, - - Y410_BT2020_SHIFT = 11, - Y410_BT2020_MASK = 1 << Y410_BT2020_SHIFT, - Y410_BT2020_OFF = 0 << Y410_BT2020_SHIFT, - Y410_BT2020_ON = 1 << Y410_BT2020_SHIFT, - }; - - inline Key() : mKey(0) {} - inline Key(const Key& rhs) : mKey(rhs.mKey) {} - - inline Key& set(key_t mask, key_t value) { - mKey = (mKey & ~mask) | value; - return *this; - } - - inline bool isTexturing() const { return (mKey & TEXTURE_MASK) != TEXTURE_OFF; } - inline int getTextureTarget() const { return (mKey & TEXTURE_MASK); } - inline bool isPremultiplied() const { return (mKey & BLEND_MASK) == BLEND_PREMULT; } - inline bool isOpaque() const { return (mKey & OPACITY_MASK) == OPACITY_OPAQUE; } - inline bool hasAlpha() const { return (mKey & ALPHA_MASK) == ALPHA_LT_ONE; } - inline bool hasInputTransformMatrix() const { - return (mKey & INPUT_TRANSFORM_MATRIX_MASK) == INPUT_TRANSFORM_MATRIX_ON; - } - inline bool hasOutputTransformMatrix() const { - return (mKey & OUTPUT_TRANSFORM_MATRIX_MASK) == OUTPUT_TRANSFORM_MATRIX_ON; - } - inline bool hasTransformMatrix() const { - return hasInputTransformMatrix() || hasOutputTransformMatrix(); - } - inline int getInputTF() const { return (mKey & INPUT_TF_MASK); } - inline int getOutputTF() const { return (mKey & OUTPUT_TF_MASK); } - - // When HDR and non-HDR contents are mixed, or different types of HDR contents are - // mixed, we will do a tone mapping process to tone map the input content to output - // content. Currently, the following conversions handled, they are: - // * SDR -> HLG - // * SDR -> PQ - // * HLG -> PQ - inline bool needsToneMapping() const { - int inputTF = getInputTF(); - int outputTF = getOutputTF(); - - // Return false when converting from SDR to SDR. - if (inputTF == Key::INPUT_TF_SRGB && outputTF == Key::OUTPUT_TF_LINEAR) { - return false; - } - if (inputTF == Key::INPUT_TF_LINEAR && outputTF == Key::OUTPUT_TF_SRGB) { - return false; - } - - inputTF >>= Key::INPUT_TF_SHIFT; - outputTF >>= Key::OUTPUT_TF_SHIFT; - return inputTF != outputTF; - } - inline bool isY410BT2020() const { return (mKey & Y410_BT2020_MASK) == Y410_BT2020_ON; } - - // this is the definition of a friend function -- not a method of class Needs - friend inline int strictly_order_type(const Key& lhs, const Key& rhs) { - return (lhs.mKey < rhs.mKey) ? 1 : 0; - } - }; - - ProgramCache(); - ~ProgramCache(); - - // Generate shaders to populate the cache - void primeCache(bool useColorManagement); - - // useProgram lookup a suitable program in the cache or generates one - // if none can be found. - void useProgram(const Description& description); - -private: - // compute a cache Key from a Description - static Key computeKey(const Description& description); - // Generate EOTF based from Key. - static void generateEOTF(Formatter& fs, const Key& needs); - // Generate necessary tone mapping methods for OOTF. - static void generateToneMappingProcess(Formatter& fs, const Key& needs); - // Generate OOTF based from Key. - static void generateOOTF(Formatter& fs, const Key& needs); - // Generate OETF based from Key. - static void generateOETF(Formatter& fs, const Key& needs); - // generates a program from the Key - static Program* generateProgram(const Key& needs); - // generates the vertex shader from the Key - static String8 generateVertexShader(const Key& needs); - // generates the fragment shader from the Key - static String8 generateFragmentShader(const Key& needs); - - // Key/Value map used for caching Programs. Currently the cache - // is never shrunk. - DefaultKeyedVector mCache; -}; - -ANDROID_BASIC_TYPES_TRAITS(ProgramCache::Key) - -} /* namespace android */ - -#endif /* SF_RENDER_ENGINE_PROGRAMCACHE_H */ diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h index 6213784f81..c532adc3ac 100644 --- a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h @@ -17,10 +17,9 @@ #ifndef SF_RENDERENGINE_H_ #define SF_RENDERENGINE_H_ -#include - #include #include +#include #include #include @@ -33,21 +32,19 @@ struct ANativeWindowBuffer; -// --------------------------------------------------------------------------- namespace android { -// --------------------------------------------------------------------------- class String8; class Rect; class Region; -class Mesh; -class Texture; -namespace RE { +namespace renderengine { +class BindNativeBufferAsFramebuffer; +class Mesh; class Image; class Surface; -class BindNativeBufferAsFramebuffer; +class Texture; namespace impl { class RenderEngine; @@ -61,8 +58,8 @@ public: virtual ~RenderEngine() = 0; - virtual std::unique_ptr createSurface() = 0; - virtual std::unique_ptr createImage() = 0; + virtual std::unique_ptr createSurface() = 0; + virtual std::unique_ptr createImage() = 0; virtual void primeCache() const = 0; @@ -73,7 +70,7 @@ public: virtual bool useWaitSync() const = 0; virtual bool isCurrent() const = 0; - virtual bool setCurrentSurface(const RE::Surface& surface) = 0; + virtual bool setCurrentSurface(const renderengine::Surface& surface) = 0; virtual void resetCurrentSurface() = 0; // helpers @@ -97,11 +94,11 @@ public: virtual void disableScissor() = 0; virtual void genTextures(size_t count, uint32_t* names) = 0; virtual void deleteTextures(size_t count, uint32_t const* names) = 0; - virtual void bindExternalTextureImage(uint32_t texName, const RE::Image& image) = 0; + virtual void bindExternalTextureImage(uint32_t texName, const renderengine::Image& image) = 0; virtual void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) = 0; virtual void bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer, - RE::BindNativeBufferAsFramebuffer* bindHelper) = 0; - virtual void unbindNativeBufferAsFrameBuffer(RE::BindNativeBufferAsFramebuffer* bindHelper) = 0; + BindNativeBufferAsFramebuffer* bindHelper) = 0; + virtual void unbindNativeBufferAsFrameBuffer(BindNativeBufferAsFramebuffer* bindHelper) = 0; // set-up virtual void checkErrors() const; @@ -155,7 +152,7 @@ namespace impl { class Image; class Surface; -class RenderEngine : public RE::RenderEngine { +class RenderEngine : public renderengine::RenderEngine { enum GlesVersion { GLES_VERSION_1_0 = 0x10000, GLES_VERSION_1_1 = 0x10001, @@ -185,8 +182,8 @@ public: // RenderEngine interface implementation - std::unique_ptr createSurface() override; - std::unique_ptr createImage() override; + std::unique_ptr createSurface() override; + std::unique_ptr createImage() override; void primeCache() const override; @@ -197,7 +194,7 @@ public: bool useWaitSync() const override; bool isCurrent() const; - bool setCurrentSurface(const RE::Surface& surface) override; + bool setCurrentSurface(const renderengine::Surface& surface) override; void resetCurrentSurface() override; // synchronization @@ -223,7 +220,7 @@ public: void disableScissor() override; void genTextures(size_t count, uint32_t* names) override; void deleteTextures(size_t count, uint32_t const* names) override; - void bindExternalTextureImage(uint32_t texName, const RE::Image& image) override; + void bindExternalTextureImage(uint32_t texName, const renderengine::Image& image) override; void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) override; void checkErrors() const override; @@ -235,12 +232,14 @@ public: EGLConfig getEGLConfig() const; // Common implementation - bool setCurrentSurface(const RE::impl::Surface& surface); - void bindExternalTextureImage(uint32_t texName, const RE::impl::Image& image); + bool setCurrentSurface(const renderengine::impl::Surface& surface); + void bindExternalTextureImage(uint32_t texName, const renderengine::impl::Image& image); - void bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer, - RE::BindNativeBufferAsFramebuffer* bindHelper) override; - void unbindNativeBufferAsFrameBuffer(RE::BindNativeBufferAsFramebuffer* bindHelper) override; + void bindNativeBufferAsFrameBuffer( + ANativeWindowBuffer* buffer, + renderengine::BindNativeBufferAsFramebuffer* bindHelper) override; + void unbindNativeBufferAsFrameBuffer( + renderengine::BindNativeBufferAsFramebuffer* bindHelper) override; // Overriden by each specialization virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, @@ -248,8 +247,8 @@ public: virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0; }; -} // namespace impl -} // namespace RE -} // namespace android +} // namespace impl +} // namespace renderengine +} // namespace android #endif /* SF_RENDERENGINE_H_ */ diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/Surface.h b/services/surfaceflinger/RenderEngine/include/renderengine/Surface.h index d4d3d8c0f5..aaa9c7b35a 100644 --- a/services/surfaceflinger/RenderEngine/include/renderengine/Surface.h +++ b/services/surfaceflinger/RenderEngine/include/renderengine/Surface.h @@ -23,7 +23,7 @@ struct ANativeWindow; namespace android { -namespace RE { +namespace renderengine { class Surface { public: @@ -48,7 +48,7 @@ namespace impl { class RenderEngine; -class Surface final : public RE::Surface { +class Surface final : public renderengine::Surface { public: Surface(const RenderEngine& engine); ~Surface(); @@ -56,7 +56,7 @@ public: Surface(const Surface&) = delete; Surface& operator=(const Surface&) = delete; - // RE::Surface implementation + // renderengine::Surface implementation void setCritical(bool enable) override { mCritical = enable; } void setAsync(bool enable) override { mAsync = enable; } @@ -90,6 +90,6 @@ private: EGLSurface mEGLSurface = EGL_NO_SURFACE; }; -} // namespace impl -} // namespace RE -} // namespace android +} // namespace impl +} // namespace renderengine +} // namespace android diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/Texture.h b/services/surfaceflinger/RenderEngine/include/renderengine/Texture.h index 56b6b31573..130037ce2c 100644 --- a/services/surfaceflinger/RenderEngine/include/renderengine/Texture.h +++ b/services/surfaceflinger/RenderEngine/include/renderengine/Texture.h @@ -14,13 +14,15 @@ * limitations under the License. */ -#include -#include - #ifndef SF_RENDER_ENGINE_TEXTURE_H #define SF_RENDER_ENGINE_TEXTURE_H +#include + +#include + namespace android { +namespace renderengine { class Texture { uint32_t mTextureName; @@ -52,5 +54,6 @@ public: size_t getHeight() const; }; -} /* namespace android */ +} // namespace renderengine +} // namespace android #endif /* SF_RENDER_ENGINE_TEXTURE_H */ diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h b/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h new file mode 100644 index 0000000000..a6301ae38d --- /dev/null +++ b/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h @@ -0,0 +1,103 @@ +/* + * Copyright 2013 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. + */ + +#ifndef SF_RENDER_ENGINE_DESCRIPTION_H_ +#define SF_RENDER_ENGINE_DESCRIPTION_H_ + +#include + +namespace android { +namespace renderengine { + +namespace gl { +class Program; +class ProgramCache; +} + +/* + * This holds the state of the rendering engine. This class is used + * to generate a corresponding GLSL program and set the appropriate + * uniform. + * + * Program and ProgramCache are friends and access the state directly + */ +class Description { +public: + Description() = default; + ~Description() = default; + + void setPremultipliedAlpha(bool premultipliedAlpha); + void setOpaque(bool opaque); + void setTexture(const Texture& texture); + void disableTexture(); + void setColor(const half4& color); + void setProjectionMatrix(const mat4& mtx); + void setColorMatrix(const mat4& mtx); + void setInputTransformMatrix(const mat3& matrix); + void setOutputTransformMatrix(const mat4& matrix); + bool hasInputTransformMatrix() const; + bool hasOutputTransformMatrix() const; + bool hasColorMatrix() const; + const mat4& getColorMatrix() const; + + void setY410BT2020(bool enable); + + enum class TransferFunction : int { + LINEAR, + SRGB, + ST2084, + HLG, // Hybrid Log-Gamma for HDR. + }; + void setInputTransferFunction(TransferFunction transferFunction); + void setOutputTransferFunction(TransferFunction transferFunction); + void setDisplayMaxLuminance(const float maxLuminance); + +private: + friend class gl::Program; + friend class gl::ProgramCache; + + // whether textures are premultiplied + bool mPremultipliedAlpha = false; + // whether this layer is marked as opaque + bool mOpaque = true; + + // Texture this layer uses + Texture mTexture; + bool mTextureEnabled = false; + + // color used when texturing is disabled or when setting alpha. + half4 mColor; + + // true if the sampled pixel values are in Y410/BT2020 rather than RGBA + bool mY410BT2020 = false; + + // transfer functions for the input/output + TransferFunction mInputTransferFunction = TransferFunction::LINEAR; + TransferFunction mOutputTransferFunction = TransferFunction::LINEAR; + + float mDisplayMaxLuminance; + + // projection matrix + mat4 mProjectionMatrix; + mat4 mColorMatrix; + mat3 mInputTransformMatrix; + mat4 mOutputTransformMatrix; +}; + +} // namespace renderengine +} // namespace android + +#endif /* SF_RENDER_ENGINE_DESCRIPTION_H_ */ diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 888dd38955..278713272f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -618,9 +618,10 @@ void SurfaceFlinger::init() { // Get a RenderEngine for the given display / config (can't fail) int32_t renderEngineFeature = 0; - renderEngineFeature |= (useColorManagement ? RE::RenderEngine::USE_COLOR_MANAGEMENT : 0); - getBE().mRenderEngine = - RE::impl::RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888, renderEngineFeature); + renderEngineFeature |= (useColorManagement ? + renderengine::RenderEngine::USE_COLOR_MANAGEMENT : 0); + getBE().mRenderEngine = renderengine::impl::RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888, + renderEngineFeature); LOG_ALWAYS_FATAL_IF(getBE().mRenderEngine == nullptr, "couldn't create RenderEngine"); LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay, @@ -2420,7 +2421,7 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( /* * Create our display's surface */ - std::unique_ptr renderSurface = getRenderEngine().createSurface(); + std::unique_ptr renderSurface = getRenderEngine().createSurface(); renderSurface->setCritical(state.type == DisplayDevice::DISPLAY_PRIMARY); renderSurface->setAsync(state.isVirtual()); renderSurface->setNativeWindow(nativeWindow.get()); @@ -5458,7 +5459,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, // this binds the given EGLImage as a framebuffer for the // duration of this scope. - RE::BindNativeBufferAsFramebuffer bufferBond(getRenderEngine(), buffer); + renderengine::BindNativeBufferAsFramebuffer bufferBond(getRenderEngine(), buffer); if (bufferBond.getStatus() != NO_ERROR) { ALOGE("got ANWB binding error while taking screenshot"); return INVALID_OPERATION; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 3dbceae89a..fad94103ec 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -106,7 +106,7 @@ namespace impl { class EventThread; } // namespace impl -namespace RE { +namespace renderengine { class RenderEngine; } @@ -175,7 +175,7 @@ public: const std::string mHwcServiceName; // "default" for real use, something else for testing. // constant members (no synchronization needed for access) - std::unique_ptr mRenderEngine; + std::unique_ptr mRenderEngine; EGLContext mEGLContext; EGLDisplay mEGLDisplay; @@ -345,7 +345,7 @@ public: // TODO: this should be made accessible only to HWComposer const Vector< sp >& getLayerSortedByZForHwcDisplay(int id); - RE::RenderEngine& getRenderEngine() const { return *getBE().mRenderEngine; } + renderengine::RenderEngine& getRenderEngine() const { return *getBE().mRenderEngine; } bool authenticateSurfaceTextureLocked( const sp& bufferProducer) const; diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index 1f57b8e309..32712c7ceb 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -116,7 +116,7 @@ public: // These mocks are created by the test, but are destroyed by SurfaceFlinger // by virtue of being stored into a std::unique_ptr. However we still need // to keep a reference to them for use in setting up call expectations. - RE::mock::RenderEngine* mRenderEngine = new RE::mock::RenderEngine(); + renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine(); Hwc2::mock::Composer* mComposer = nullptr; mock::MessageQueue* mMessageQueue = new mock::MessageQueue(); mock::SurfaceInterceptor* mSurfaceInterceptor = new mock::SurfaceInterceptor(); @@ -127,7 +127,7 @@ public: sp mProducer; mock::NativeWindowSurface* mNativeWindowSurface = nullptr; sp mNativeWindow; - RE::mock::Surface* mRenderSurface = nullptr; + renderengine::mock::Surface* mRenderSurface = nullptr; }; DisplayTransactionTest::DisplayTransactionTest() { @@ -155,7 +155,7 @@ DisplayTransactionTest::DisplayTransactionTest() { mFlinger.mutableEventControlThread().reset(mEventControlThread); mFlinger.mutableEventThread().reset(mEventThread); mFlinger.mutableEventQueue().reset(mMessageQueue); - mFlinger.setupRenderEngine(std::unique_ptr(mRenderEngine)); + mFlinger.setupRenderEngine(std::unique_ptr(mRenderEngine)); mFlinger.mutableInterceptor().reset(mSurfaceInterceptor); mFlinger.mutablePrimaryDispSync().reset(mPrimaryDispSync); @@ -277,9 +277,10 @@ struct DisplayVariant { // For simplicity, we only expect to create a single render surface for // each test. ASSERT_TRUE(test->mRenderSurface == nullptr); - test->mRenderSurface = new RE::mock::Surface(); + test->mRenderSurface = new renderengine::mock::Surface(); EXPECT_CALL(*test->mRenderEngine, createSurface()) - .WillOnce(Return(ByMove(std::unique_ptr(test->mRenderSurface)))); + .WillOnce(Return(ByMove( + std::unique_ptr(test->mRenderSurface)))); EXPECT_CALL(*test->mRenderSurface, setAsync(static_cast(ASYNC))).Times(1); EXPECT_CALL(*test->mRenderSurface, setCritical(static_cast(CRITICAL))).Times(1); EXPECT_CALL(*test->mRenderSurface, setNativeWindow(test->mNativeWindow.get())).Times(1); @@ -1735,11 +1736,11 @@ TEST_F(HandleTransactionLockedTest, processesDisplayWidthChanges) { // A display is set up auto nativeWindow = new mock::NativeWindow(); auto displaySurface = new mock::DisplaySurface(); - auto renderSurface = new RE::mock::Surface(); + auto renderSurface = new renderengine::mock::Surface(); auto display = Case::Display::makeFakeExistingDisplayInjector(this); display.setNativeWindow(nativeWindow); display.setDisplaySurface(displaySurface); - display.setRenderSurface(std::unique_ptr(renderSurface)); + display.setRenderSurface(std::unique_ptr(renderSurface)); display.inject(); // There is a change to the viewport state @@ -1776,11 +1777,11 @@ TEST_F(HandleTransactionLockedTest, processesDisplayHeightChanges) { // A display is set up auto nativeWindow = new mock::NativeWindow(); auto displaySurface = new mock::DisplaySurface(); - auto renderSurface = new RE::mock::Surface(); + auto renderSurface = new renderengine::mock::Surface(); auto display = Case::Display::makeFakeExistingDisplayInjector(this); display.setNativeWindow(nativeWindow); display.setDisplaySurface(displaySurface); - display.setRenderSurface(std::unique_ptr(renderSurface)); + display.setRenderSurface(std::unique_ptr(renderSurface)); display.inject(); // There is a change to the viewport state diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index d8e7581290..b0103df759 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -23,7 +23,7 @@ namespace android { class EventThread; -namespace RE { +namespace renderengine { class RenderEngine; } @@ -36,7 +36,7 @@ public: // Extend this as needed for accessing SurfaceFlinger private (and public) // functions. - void setupRenderEngine(std::unique_ptr renderEngine) { + void setupRenderEngine(std::unique_ptr renderEngine) { mFlinger->getBE().mRenderEngine = std::move(renderEngine); } @@ -313,7 +313,7 @@ public: return *this; } - auto& setRenderSurface(std::unique_ptr renderSurface) { + auto& setRenderSurface(std::unique_ptr renderSurface) { mRenderSurface = std::move(renderSurface); return *this; } @@ -352,7 +352,7 @@ public: const int32_t mDisplayId; sp mNativeWindow; sp mDisplaySurface; - std::unique_ptr mRenderSurface; + std::unique_ptr mRenderSurface; bool mSecure = false; }; diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp index 200f2148bc..06ef0b253e 100644 --- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp +++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp @@ -19,7 +19,7 @@ #include namespace android { -namespace RE { +namespace renderengine { namespace mock { // Explicit default instantiation is recommended. @@ -33,5 +33,5 @@ Image::Image() = default; Image::~Image() = default; } // namespace mock -} // namespace RE +} // namespace renderengine } // namespace android diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h index b907c492a2..bf3c09af07 100644 --- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h +++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h @@ -25,22 +25,22 @@ #include namespace android { -namespace RE { +namespace renderengine { namespace mock { -class RenderEngine : public RE::RenderEngine { +class RenderEngine : public renderengine::RenderEngine { public: RenderEngine(); ~RenderEngine() override; - MOCK_METHOD0(createSurface, std::unique_ptr()); - MOCK_METHOD0(createImage, std::unique_ptr()); + MOCK_METHOD0(createSurface, std::unique_ptr()); + MOCK_METHOD0(createImage, std::unique_ptr()); MOCK_CONST_METHOD0(primeCache, void()); MOCK_METHOD1(dump, void(String8&)); MOCK_CONST_METHOD0(useNativeFenceSync, bool()); MOCK_CONST_METHOD0(useWaitSync, bool()); MOCK_CONST_METHOD0(isCurrent, bool()); - MOCK_METHOD1(setCurrentSurface, bool(const RE::Surface&)); + MOCK_METHOD1(setCurrentSurface, bool(const renderengine::Surface&)); MOCK_METHOD0(resetCurrentSurface, void()); MOCK_METHOD0(flush, base::unique_fd()); MOCK_METHOD0(finish, bool()); @@ -52,7 +52,7 @@ public: MOCK_METHOD0(disableScissor, void()); MOCK_METHOD2(genTextures, void(size_t, uint32_t*)); MOCK_METHOD2(deleteTextures, void(size_t, uint32_t const*)); - MOCK_METHOD2(bindExternalTextureImage, void(uint32_t, const RE::Image&)); + MOCK_METHOD2(bindExternalTextureImage, void(uint32_t, const renderengine::Image&)); MOCK_METHOD5(readPixels, void(size_t, size_t, size_t, size_t, uint32_t*)); MOCK_CONST_METHOD0(checkErrors, void()); MOCK_METHOD6(setViewportAndProjection, @@ -70,14 +70,16 @@ public: MOCK_METHOD1(setOutputDataSpace, void(ui::Dataspace)); MOCK_METHOD1(setDisplayMaxLuminance, void(const float)); MOCK_METHOD2(bindNativeBufferAsFrameBuffer, - void(ANativeWindowBuffer*, RE::BindNativeBufferAsFramebuffer*)); - MOCK_METHOD1(unbindNativeBufferAsFrameBuffer, void(RE::BindNativeBufferAsFramebuffer*)); + void(ANativeWindowBuffer*, + renderengine::BindNativeBufferAsFramebuffer*)); + MOCK_METHOD1(unbindNativeBufferAsFrameBuffer, + void(renderengine::BindNativeBufferAsFramebuffer*)); MOCK_METHOD1(drawMesh, void(const Mesh&)); MOCK_CONST_METHOD0(getMaxTextureSize, size_t()); MOCK_CONST_METHOD0(getMaxViewportDims, size_t()); }; -class Surface : public RE::Surface { +class Surface : public renderengine::Surface { public: Surface(); ~Surface() override; @@ -94,7 +96,7 @@ public: MOCK_CONST_METHOD0(queryHeight, int32_t()); }; -class Image : public RE::Image { +class Image : public renderengine::Image { public: Image(); ~Image() override; @@ -104,5 +106,5 @@ public: }; } // namespace mock -} // namespace RE +} // namespace renderengine } // namespace android -- cgit v1.2.3-59-g8ed1b From 5f6664c1c41c775aa8647264d4d881aa789ab9ff Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Tue, 28 Aug 2018 11:01:44 -0700 Subject: surfaceflinger: improve RenderArea needsFiltering Compare source crop (instead of the logical render area) against physical render area to decide whether filtering is required. This allows us to get rid of Layer::setFiltering. As a result, captureLayers for Recents no longer enables filtering. Screenshots under landscape mode no longer enables filtering. Bug: 113041375 Test: take screenshot, rotate screen, screencap Change-Id: Ida95fdfec3a0dde7a19adf35c91bf3d570bab6bb --- services/surfaceflinger/BufferLayer.cpp | 2 +- services/surfaceflinger/DisplayDevice.h | 15 ++++++++++++++- services/surfaceflinger/Layer.cpp | 9 --------- services/surfaceflinger/Layer.h | 5 ----- services/surfaceflinger/SurfaceFlinger.cpp | 21 ++++++++------------- 5 files changed, 23 insertions(+), 29 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 1bb7a85628..2d6f79ceb6 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -180,7 +180,7 @@ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, if (!blackOutLayer) { // TODO: we could be more subtle with isFixedSize() - const bool useFiltering = getFiltering() || needsFiltering(renderArea) || isFixedSize(); + const bool useFiltering = needsFiltering(renderArea) || isFixedSize(); // Query the texture matrix given our current filtering mode. float textureMatrix[16]; diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 3613e1ac2b..f7ffffdcec 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -353,7 +353,20 @@ public: int getHeight() const override { return mDevice->getHeight(); } int getWidth() const override { return mDevice->getWidth(); } bool isSecure() const override { return mDevice->isSecure(); } - bool needsFiltering() const override { return mDevice->needsFiltering(); } + + bool needsFiltering() const override { + if (mDevice->needsFiltering()) { + return true; + } + + const Rect sourceCrop = getSourceCrop(); + int width = sourceCrop.width(); + int height = sourceCrop.height(); + if (getRotationFlags() & ui::Transform::ROT_90) { + std::swap(width, height); + } + return width != getReqWidth() || height != getReqHeight(); + } Rect getSourceCrop() const override { const int orientation = mDevice->getInstallOrientation(); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index c7d67e2298..f472931d37 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -78,7 +78,6 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n mOverrideScalingMode(-1), mCurrentFrameNumber(0), mFrameLatencyNeeded(false), - mFiltering(false), mNeedsFiltering(false), mProtectedByApp(false), mClientRef(client), @@ -768,14 +767,6 @@ bool Layer::addSyncPoint(const std::shared_ptr& point) { return true; } -void Layer::setFiltering(bool filtering) { - mFiltering = filtering; -} - -bool Layer::getFiltering() const { - return mFiltering; -} - // ---------------------------------------------------------------------------- // local state // ---------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 604ec656fc..1fa7341ca0 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -512,9 +512,6 @@ public: // ----------------------------------------------------------------------- void clearWithOpenGL(const RenderArea& renderArea) const; - void setFiltering(bool filtering); - bool getFiltering() const; - inline const State& getDrawingState() const { return mDrawingState; } inline const State& getCurrentState() const { return mCurrentState; } @@ -731,8 +728,6 @@ protected: int32_t mOverrideScalingMode; std::atomic mCurrentFrameNumber; bool mFrameLatencyNeeded; - // Whether filtering is forced on or not - bool mFiltering; // Whether filtering is needed b/c of the drawingstate bool mNeedsFiltering; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e258897348..8dc63f6243 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5119,6 +5119,7 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, : RenderArea(reqWidth, reqHeight, CaptureFill::CLEAR), mLayer(layer), mCrop(crop), + mNeedsFiltering(false), mFlinger(flinger), mChildrenOnly(childrenOnly) {} const ui::Transform& getTransform() const override { return mTransform; } @@ -5131,7 +5132,7 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, } int getWidth() const override { return mLayer->getActiveWidth(mLayer->getDrawingState()); } bool isSecure() const override { return false; } - bool needsFiltering() const override { return false; } + bool needsFiltering() const override { return mNeedsFiltering; } Rect getSourceCrop() const override { if (mCrop.isEmpty()) { return getBounds(); @@ -5152,6 +5153,11 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, }; void render(std::function drawLayers) override { + const Rect sourceCrop = getSourceCrop(); + // no need to check rotation because there is none + mNeedsFiltering = sourceCrop.width() != getReqWidth() || + sourceCrop.height() != getReqHeight(); + if (!mChildrenOnly) { mTransform = mLayer->getTransform().inverse(); drawLayers(); @@ -5174,6 +5180,7 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, // layer which has no properties set and which does not draw. sp screenshotParentLayer; ui::Transform mTransform; + bool mNeedsFiltering; SurfaceFlinger* mFlinger; const bool mChildrenOnly; @@ -5312,7 +5319,6 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, auto& engine(getRenderEngine()); // get screen geometry - const auto raWidth = renderArea.getWidth(); const auto raHeight = renderArea.getHeight(); const auto reqWidth = renderArea.getReqWidth(); @@ -5320,15 +5326,6 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, const auto sourceCrop = renderArea.getSourceCrop(); const auto rotation = renderArea.getRotationFlags(); - bool filtering = false; - if (primaryDisplayOrientation & DisplayState::eOrientationSwapMask) { - filtering = static_cast(reqWidth) != raHeight || - static_cast(reqHeight) != raWidth; - } else { - filtering = static_cast(reqWidth) != raWidth || - static_cast(reqHeight) != raHeight; - } - // assume ColorMode::SRGB / RenderIntent::COLORIMETRIC engine.setOutputDataSpace(Dataspace::SRGB); engine.setDisplayMaxLuminance(DisplayDevice::sDefaultMaxLumiance); @@ -5346,9 +5343,7 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, engine.clearWithColor(0, 0, 0, alpha); traverseLayers([&](Layer* layer) { - if (filtering) layer->setFiltering(true); layer->draw(renderArea, useIdentityTransform); - if (filtering) layer->setFiltering(false); }); } -- cgit v1.2.3-59-g8ed1b From dcce0e2462c9bd0b6ac0db3f95c43cd2b9222eb2 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Thu, 23 Aug 2018 08:35:19 -0700 Subject: SF: Remove setFinalCrop impl 2/2 setFinalCrop functionality is reimplemented by creating a new bounds layer and applying a crop on this layer. see ag/4625718 Test: mmma frameworks/native/services/surfaceflinger/tests/ && \ mmma frameworks/native/libs/gui/tests/ && adb sync data && \ adb shell /data/nativetest64/libgui_test/libgui_test && \ adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest && \ adb shell /data/nativetest64/SurfaceFlinger_test/SurfaceFlinger_test && \ adb shell /data/nativetest64/SurfaceParcelable_test/SurfaceParcelable_test && \ adb shell /data/nativetest64/sffakehwc_test/sffakehwc_test && \ echo "ALL TESTS PASSED" Change-Id: I9be511c07a3351a2947afb2beed10ce2a462b635 --- cmds/surfacereplayer/proto/src/trace.proto | 7 +- cmds/surfacereplayer/replayer/Replayer.cpp | 13 -- cmds/surfacereplayer/replayer/Replayer.h | 2 - libs/gui/LayerDebugInfo.cpp | 5 +- libs/gui/LayerState.cpp | 6 - libs/gui/SurfaceComposerClient.cpp | 12 -- libs/gui/include/gui/LayerDebugInfo.h | 1 - libs/gui/include/gui/LayerState.h | 39 ++-- libs/gui/include/gui/SurfaceComposerClient.h | 1 - services/surfaceflinger/BufferLayer.cpp | 11 -- services/surfaceflinger/BufferStateLayer.h | 2 - services/surfaceflinger/Layer.cpp | 69 +------ services/surfaceflinger/Layer.h | 7 - services/surfaceflinger/LayerRejecter.cpp | 5 - services/surfaceflinger/SurfaceFlinger.cpp | 4 - services/surfaceflinger/SurfaceInterceptor.cpp | 13 -- services/surfaceflinger/SurfaceInterceptor.h | 1 - .../surfaceflinger/layerproto/LayerProtoParser.cpp | 4 +- .../include/layerproto/LayerProtoParser.h | 1 - services/surfaceflinger/layerproto/layers.proto | 2 +- .../tests/SurfaceFlinger_test.filter | 2 +- .../tests/SurfaceInterceptor_test.cpp | 30 --- services/surfaceflinger/tests/Transaction_test.cpp | 216 --------------------- .../tests/fakehwc/SFFakeHwc_test.cpp | 156 --------------- 24 files changed, 24 insertions(+), 585 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto index 0bc08a91ab..68ddeb02d6 100644 --- a/cmds/surfacereplayer/proto/src/trace.proto +++ b/cmds/surfacereplayer/proto/src/trace.proto @@ -30,14 +30,13 @@ message Transaction { message SurfaceChange { required int32 id = 1; - + reserved 7; oneof SurfaceChange { PositionChange position = 2; SizeChange size = 3; AlphaChange alpha = 4; LayerChange layer = 5; CropChange crop = 6; - FinalCropChange final_crop = 7; MatrixChange matrix = 8; OverrideScalingModeChange override_scaling_mode = 9; TransparentRegionHintChange transparent_region_hint = 10; @@ -71,10 +70,6 @@ message CropChange { required Rectangle rectangle = 1; } -message FinalCropChange { - required Rectangle rectangle = 1; -} - message MatrixChange { required float dsdx = 1; required float dtdx = 2; diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index d9ff4ba59f..66025468ea 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -388,9 +388,6 @@ status_t Replayer::doSurfaceTransaction( case SurfaceChange::SurfaceChangeCase::kMatrix: setMatrix(transaction, change.id(), change.matrix()); break; - case SurfaceChange::SurfaceChangeCase::kFinalCrop: - setFinalCrop(transaction, change.id(), change.final_crop()); - break; case SurfaceChange::SurfaceChangeCase::kOverrideScalingMode: setOverrideScalingMode(transaction, change.id(), change.override_scaling_mode()); @@ -492,16 +489,6 @@ void Replayer::setCrop(SurfaceComposerClient::Transaction& t, t.setCrop_legacy(mLayers[id], r); } -void Replayer::setFinalCrop(SurfaceComposerClient::Transaction& t, - layer_id id, const FinalCropChange& fcc) { - ALOGV("Layer %d: Setting Final Crop -- left=%d, top=%d, right=%d, bottom=%d", id, - fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(), - fcc.rectangle().bottom()); - Rect r = Rect(fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(), - fcc.rectangle().bottom()); - t.setFinalCrop_legacy(mLayers[id], r); -} - void Replayer::setMatrix(SurfaceComposerClient::Transaction& t, layer_id id, const MatrixChange& mc) { ALOGV("Layer %d: Setting Matrix -- dsdx=%f, dtdx=%f, dsdy=%f, dtdy=%f", id, mc.dsdx(), diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h index 295403eace..68390d33ae 100644 --- a/cmds/surfacereplayer/replayer/Replayer.h +++ b/cmds/surfacereplayer/replayer/Replayer.h @@ -92,8 +92,6 @@ class Replayer { layer_id id, const LayerChange& lc); void setCrop(SurfaceComposerClient::Transaction& t, layer_id id, const CropChange& cc); - void setFinalCrop(SurfaceComposerClient::Transaction& t, - layer_id id, const FinalCropChange& fcc); void setMatrix(SurfaceComposerClient::Transaction& t, layer_id id, const MatrixChange& mc); void setOverrideScalingMode(SurfaceComposerClient::Transaction& t, diff --git a/libs/gui/LayerDebugInfo.cpp b/libs/gui/LayerDebugInfo.cpp index d3dc16d30e..ccde9e08e1 100644 --- a/libs/gui/LayerDebugInfo.cpp +++ b/libs/gui/LayerDebugInfo.cpp @@ -42,7 +42,6 @@ status_t LayerDebugInfo::writeToParcel(Parcel* parcel) const { RETURN_ON_ERROR(parcel->writeInt32(mWidth)); RETURN_ON_ERROR(parcel->writeInt32(mHeight)); RETURN_ON_ERROR(parcel->write(mCrop)); - RETURN_ON_ERROR(parcel->write(mFinalCrop)); RETURN_ON_ERROR(parcel->writeFloat(mColor.r)); RETURN_ON_ERROR(parcel->writeFloat(mColor.g)); RETURN_ON_ERROR(parcel->writeFloat(mColor.b)); @@ -81,7 +80,6 @@ status_t LayerDebugInfo::readFromParcel(const Parcel* parcel) { RETURN_ON_ERROR(parcel->readInt32(&mWidth)); RETURN_ON_ERROR(parcel->readInt32(&mHeight)); RETURN_ON_ERROR(parcel->read(mCrop)); - RETURN_ON_ERROR(parcel->read(mFinalCrop)); mColor.r = parcel->readFloat(); RETURN_ON_ERROR(parcel->errorCheck()); mColor.g = parcel->readFloat(); @@ -121,8 +119,7 @@ std::string to_string(const LayerDebugInfo& info) { info.mLayerStack, info.mZ, static_cast(info.mX), static_cast(info.mY), info.mWidth, info.mHeight); - result.appendFormat("crop=%s, finalCrop=%s, ", - to_string(info.mCrop).c_str(), to_string(info.mFinalCrop).c_str()); + result.appendFormat("crop=%s, ", to_string(info.mCrop).c_str()); result.appendFormat("isOpaque=%1d, invalidate=%1d, ", info.mIsOpaque, info.mContentDirty); result.appendFormat("dataspace=%s, ", dataspaceDetails(info.mDataSpace).c_str()); result.appendFormat("pixelformat=%s, ", decodePixelFormat(info.mPixelFormat).c_str()); diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 05c24c5e1a..deb8ea8f7e 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -38,7 +38,6 @@ status_t layer_state_t::write(Parcel& output) const *reinterpret_cast( output.writeInplace(sizeof(layer_state_t::matrix22_t))) = matrix; output.write(crop_legacy); - output.write(finalCrop_legacy); output.writeStrongBinder(barrierHandle_legacy); output.writeStrongBinder(reparentHandle); output.writeUint64(frameNumber_legacy); @@ -99,7 +98,6 @@ status_t layer_state_t::read(const Parcel& input) return BAD_VALUE; } input.read(crop_legacy); - input.read(finalCrop_legacy); barrierHandle_legacy = input.readStrongBinder(); reparentHandle = input.readStrongBinder(); frameNumber_legacy = input.readUint64(); @@ -248,10 +246,6 @@ void layer_state_t::merge(const layer_state_t& other) { barrierGbp_legacy = other.barrierGbp_legacy; frameNumber_legacy = other.frameNumber_legacy; } - if (other.what & eFinalCropChanged_legacy) { - what |= eFinalCropChanged_legacy; - finalCrop_legacy = other.finalCrop_legacy; - } if (other.what & eOverrideScalingModeChanged) { what |= eOverrideScalingModeChanged; overrideScalingMode = other.overrideScalingMode; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index b8465e37a6..f913977544 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -353,18 +353,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCrop_ return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFinalCrop_legacy( - const sp& sc, const Rect& crop) { - layer_state_t* s = getLayerState(sc); - if (!s) { - mStatus = BAD_INDEX; - return *this; - } - s->what |= layer_state_t::eFinalCropChanged_legacy; - s->finalCrop_legacy = crop; - return *this; -} - SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTransactionUntil_legacy(const sp& sc, const sp& handle, diff --git a/libs/gui/include/gui/LayerDebugInfo.h b/libs/gui/include/gui/LayerDebugInfo.h index 92bd8c5b28..66a7b4dc06 100644 --- a/libs/gui/include/gui/LayerDebugInfo.h +++ b/libs/gui/include/gui/LayerDebugInfo.h @@ -52,7 +52,6 @@ public: int32_t mWidth = -1; int32_t mHeight = -1; Rect mCrop = Rect::INVALID_RECT; - Rect mFinalCrop = Rect::INVALID_RECT; half4 mColor = half4(1.0_hf, 1.0_hf, 1.0_hf, 0.0_hf); uint32_t mFlags = 0; PixelFormat mPixelFormat = PIXEL_FORMAT_NONE; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 098179864a..0859aff8fa 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -54,25 +54,24 @@ struct layer_state_t { eLayerStackChanged = 0x00000080, eCropChanged_legacy = 0x00000100, eDeferTransaction_legacy = 0x00000200, - eFinalCropChanged_legacy = 0x00000400, - eOverrideScalingModeChanged = 0x00000800, - eGeometryAppliesWithResize = 0x00001000, - eReparentChildren = 0x00002000, - eDetachChildren = 0x00004000, - eRelativeLayerChanged = 0x00008000, - eReparent = 0x00010000, - eColorChanged = 0x00020000, - eDestroySurface = 0x00040000, - eTransformChanged = 0x00100000, - eTransformToDisplayInverseChanged = 0x00200000, - eCropChanged = 0x00400000, - eBufferChanged = 0x00800000, - eAcquireFenceChanged = 0x01000000, - eDataspaceChanged = 0x02000000, - eHdrMetadataChanged = 0x04000000, - eSurfaceDamageRegionChanged = 0x08000000, - eApiChanged = 0x10000000, - eSidebandStreamChanged = 0x20000000, + eOverrideScalingModeChanged = 0x00000400, + eGeometryAppliesWithResize = 0x00000800, + eReparentChildren = 0x00001000, + eDetachChildren = 0x00002000, + eRelativeLayerChanged = 0x00004000, + eReparent = 0x00008000, + eColorChanged = 0x00010000, + eDestroySurface = 0x00020000, + eTransformChanged = 0x00040000, + eTransformToDisplayInverseChanged = 0x00080000, + eCropChanged = 0x00100000, + eBufferChanged = 0x00200000, + eAcquireFenceChanged = 0x00400000, + eDataspaceChanged = 0x00800000, + eHdrMetadataChanged = 0x01000000, + eSurfaceDamageRegionChanged = 0x02000000, + eApiChanged = 0x04000000, + eSidebandStreamChanged = 0x08000000, }; layer_state_t() @@ -88,7 +87,6 @@ struct layer_state_t { mask(0), reserved(0), crop_legacy(Rect::INVALID_RECT), - finalCrop_legacy(Rect::INVALID_RECT), frameNumber_legacy(0), overrideScalingMode(-1), transform(0), @@ -126,7 +124,6 @@ struct layer_state_t { uint8_t reserved; matrix22_t matrix; Rect crop_legacy; - Rect finalCrop_legacy; sp barrierHandle_legacy; sp reparentHandle; uint64_t frameNumber_legacy; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 9bd1131ec0..539e46c12d 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -204,7 +204,6 @@ public: Transaction& setMatrix(const sp& sc, float dsdx, float dtdx, float dtdy, float dsdy); Transaction& setCrop_legacy(const sp& sc, const Rect& crop); - Transaction& setFinalCrop_legacy(const sp& sc, const Rect& crop); Transaction& setLayerStack(const sp& sc, uint32_t layerStack); // Defers applying any changes made in this transaction until the Layer // identified by handle reaches the given frameNumber. If the Layer identified diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 3e2fb2e408..0550b3527a 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -589,17 +589,6 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT ui::Transform t = getTransform(); Rect win = bounds; - Rect finalCrop = getFinalCrop(s); - if (!finalCrop.isEmpty()) { - win = t.transform(win); - if (!win.intersect(finalCrop, &win)) { - win.clear(); - } - win = t.inverse().transform(win); - if (!win.intersect(bounds, &win)) { - win.clear(); - } - } float left = float(win.left) / float(getActiveWidth(s)); float top = float(win.top) / float(getActiveHeight(s)); diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 5cc8d567b9..ac3aad14b4 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -58,7 +58,6 @@ public: return s.transparentRegionHint; } Rect getCrop(const Layer::State& s) const; - Rect getFinalCrop(const Layer::State& /*s*/) const { return Rect::EMPTY_RECT; } bool setTransform(uint32_t transform) override; bool setTransformToDisplayInverse(bool transformToDisplayInverse) override; @@ -79,7 +78,6 @@ public: // Override to ignore legacy layer state properties that are not used by BufferStateLayer bool setCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; }; - bool setFinalCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; }; void deferTransactionUntil_legacy(const sp& /*barrierHandle*/, uint64_t /*frameNumber*/) override {} void deferTransactionUntil_legacy(const sp& /*barrierLayer*/, diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index d2ab1b3d48..edd5cd1716 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -103,8 +103,6 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n mCurrentState.flags = layerFlags; mCurrentState.active_legacy.transform.set(0, 0); mCurrentState.crop_legacy.makeInvalid(); - mCurrentState.finalCrop_legacy.makeInvalid(); - mCurrentState.requestedFinalCrop_legacy = mCurrentState.finalCrop_legacy; mCurrentState.requestedCrop_legacy = mCurrentState.crop_legacy; mCurrentState.z = 0; mCurrentState.color.a = 1.0f; @@ -298,11 +296,6 @@ Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { ui::Transform t = getTransform(); win = t.transform(win); - Rect finalCrop = getFinalCrop(s); - if (!finalCrop.isEmpty()) { - win.intersect(finalCrop, &win); - } - const sp& p = mDrawingParent.promote(); // Now we need to calculate the parent bounds, so we can clip ourselves to those. // When calculating the parent bounds for purposes of clipping, @@ -351,13 +344,9 @@ FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const { ui::Transform t = s.active_legacy.transform; - if (p != nullptr || !s.finalCrop_legacy.isEmpty()) { + if (p != nullptr) { floatWin = t.transform(floatWin); floatWin = floatWin.intersect(parentBounds); - - if (!s.finalCrop_legacy.isEmpty()) { - floatWin = floatWin.intersect(s.finalCrop_legacy.toFloatRect()); - } floatWin = t.inverse().transform(floatWin); } @@ -388,12 +377,6 @@ Rect Layer::computeInitialCrop(const sp& display) const { if (!activeCrop.intersect(display->getViewport(), &activeCrop)) { activeCrop.clear(); } - Rect finalCrop = getFinalCrop(s); - if (!finalCrop.isEmpty()) { - if (!activeCrop.intersect(finalCrop, &activeCrop)) { - activeCrop.clear(); - } - } const auto& p = mDrawingParent.promote(); if (p != nullptr) { @@ -554,12 +537,6 @@ void Layer::setGeometry(const sp& display, uint32_t z) { // computeBounds returns a FloatRect to provide more accuracy during the // transformation. We then round upon constructing 'frame'. Rect frame{t.transform(computeBounds(activeTransparentRegion))}; - Rect finalCrop = getFinalCrop(s); - if (!finalCrop.isEmpty()) { - if (!frame.intersect(finalCrop, &frame)) { - frame.clear(); - } - } if (!frame.intersect(display->getViewport(), &frame)) { frame.clear(); } @@ -671,10 +648,6 @@ void Layer::updateCursorPosition(const sp& display) { Rect bounds = reduce(win, getActiveTransparentRegion(s)); Rect frame(getTransform().transform(bounds)); frame.intersect(display->getViewport(), &frame); - Rect finalCrop = getFinalCrop(s); - if (!finalCrop.isEmpty()) { - frame.intersect(finalCrop, &frame); - } auto& displayTransform = display->getTransform(); auto position = displayTransform.transform(frame); @@ -780,25 +753,9 @@ bool Layer::getFiltering() const { // local state // ---------------------------------------------------------------------------- -static void boundPoint(vec2* point, const Rect& crop) { - if (point->x < crop.left) { - point->x = crop.left; - } - if (point->x > crop.right) { - point->x = crop.right; - } - if (point->y < crop.top) { - point->y = crop.top; - } - if (point->y > crop.bottom) { - point->y = crop.bottom; - } -} - void Layer::computeGeometry(const RenderArea& renderArea, renderengine::Mesh& mesh, bool useIdentityTransform) const { - const Layer::State& s(getDrawingState()); const ui::Transform renderAreaTransform(renderArea.getTransform()); const uint32_t height = renderArea.getHeight(); FloatRect win = computeBounds(); @@ -816,14 +773,6 @@ void Layer::computeGeometry(const RenderArea& renderArea, rt = layerTransform.transform(rt); } - Rect finalCrop = getFinalCrop(s); - if (!finalCrop.isEmpty()) { - boundPoint(<, finalCrop); - boundPoint(&lb, finalCrop); - boundPoint(&rb, finalCrop); - boundPoint(&rt, finalCrop); - } - renderengine::Mesh::VertexArray position(mesh.getPositionArray()); position[0] = renderAreaTransform.transform(lt); position[1] = renderAreaTransform.transform(lb); @@ -1292,20 +1241,6 @@ bool Layer::setCrop_legacy(const Rect& crop, bool immediate) { return true; } -bool Layer::setFinalCrop_legacy(const Rect& crop, bool immediate) { - if (mCurrentState.requestedFinalCrop_legacy == crop) return false; - mCurrentState.sequence++; - mCurrentState.requestedFinalCrop_legacy = crop; - if (immediate && !mFreezeGeometryUpdates) { - mCurrentState.finalCrop_legacy = crop; - } - mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate; - - mCurrentState.modified = true; - setTransactionFlags(eTransactionNeeded); - return true; -} - bool Layer::setOverrideScalingMode(int32_t scalingMode) { if (scalingMode == mOverrideScalingMode) return false; mOverrideScalingMode = scalingMode; @@ -1417,7 +1352,6 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mWidth = ds.active_legacy.w; info.mHeight = ds.active_legacy.h; info.mCrop = ds.crop_legacy; - info.mFinalCrop = ds.finalCrop_legacy; info.mColor = ds.color; info.mFlags = ds.flags; info.mPixelFormat = getPixelFormat(); @@ -1955,7 +1889,6 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) size->set_h(state.active_legacy.h); LayerProtoHelper::writeToProto(state.crop_legacy, layerInfo->mutable_crop()); - LayerProtoHelper::writeToProto(state.finalCrop_legacy, layerInfo->mutable_final_crop()); layerInfo->set_is_opaque(isOpaque(state)); layerInfo->set_invalidate(contentDirty); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 56261b9268..0a169efb66 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -129,10 +129,6 @@ public: Rect crop_legacy; Rect requestedCrop_legacy; - // finalCrop is expressed in display space coordinate. - Rect finalCrop_legacy; - Rect requestedFinalCrop_legacy; - // If set, defers this state update until the identified Layer // receives a frame with the given frameNumber wp barrierLayer_legacy; @@ -225,8 +221,6 @@ public: virtual bool setPosition(float x, float y, bool immediate); // Buffer space virtual bool setCrop_legacy(const Rect& crop, bool immediate); - // Parent buffer space/display space - virtual bool setFinalCrop_legacy(const Rect& crop, bool immediate); // TODO(b/38182121): Could we eliminate the various latching modes by // using the layer hierarchy? @@ -351,7 +345,6 @@ public: return s.activeTransparentRegion_legacy; } virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; } - virtual Rect getFinalCrop(const Layer::State& s) const { return s.finalCrop_legacy; } protected: /* diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp index 136cdc03f7..72abea8b2d 100644 --- a/services/surfaceflinger/LayerRejecter.cpp +++ b/services/surfaceflinger/LayerRejecter.cpp @@ -90,11 +90,6 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) mCurrent.crop_legacy = mFront.requestedCrop_legacy; mRecomputeVisibleRegions = true; } - if (mFront.finalCrop_legacy != mFront.requestedFinalCrop_legacy) { - mFront.finalCrop_legacy = mFront.requestedFinalCrop_legacy; - mCurrent.finalCrop_legacy = mFront.requestedFinalCrop_legacy; - mRecomputeVisibleRegions = true; - } } ALOGD_IF(DEBUG_RESIZE, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 00e2bbdf39..3c8c92e2fa 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3570,10 +3570,6 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState if (layer->setCrop_legacy(s.crop_legacy, !geometryAppliesWithResize)) flags |= eTraversalNeeded; } - if (what & layer_state_t::eFinalCropChanged_legacy) { - if (layer->setFinalCrop_legacy(s.finalCrop_legacy, !geometryAppliesWithResize)) - flags |= eTraversalNeeded; - } if (what & layer_state_t::eLayerStackChanged) { ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); // We only allow setting layer stacks for top level layers, diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index f504c13a97..0b4c6fcb79 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -113,7 +113,6 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, layer->mCurrentState.barrierLayer_legacy.promote(), layer->mCurrentState.frameNumber_legacy); } - addFinalCropLocked(transaction, layerId, layer->mCurrentState.finalCrop_legacy); addOverrideScalingModeLocked(transaction, layerId, layer->getEffectiveScalingMode()); addFlagsLocked(transaction, layerId, layer->mCurrentState.flags); } @@ -289,15 +288,6 @@ void SurfaceInterceptor::addCropLocked(Transaction* transaction, int32_t layerId setProtoRectLocked(protoRect, rect); } -void SurfaceInterceptor::addFinalCropLocked(Transaction* transaction, int32_t layerId, - const Rect& rect) -{ - SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); - FinalCropChange* finalCropChange(change->mutable_final_crop()); - Rectangle* protoRect(finalCropChange->mutable_rectangle()); - setProtoRectLocked(protoRect, rect); -} - void SurfaceInterceptor::addDeferTransactionLocked(Transaction* transaction, int32_t layerId, const sp& layer, uint64_t frameNumber) { @@ -374,9 +364,6 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, } addDeferTransactionLocked(transaction, layerId, otherLayer, state.frameNumber_legacy); } - if (state.what & layer_state_t::eFinalCropChanged_legacy) { - addFinalCropLocked(transaction, layerId, state.finalCrop_legacy); - } if (state.what & layer_state_t::eOverrideScalingModeChanged) { addOverrideScalingModeLocked(transaction, layerId, state.overrideScalingMode); } diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index 218a1d2d22..394b99b415 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -146,7 +146,6 @@ private: void addCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect); void addDeferTransactionLocked(Transaction* transaction, int32_t layerId, const sp& layer, uint64_t frameNumber); - void addFinalCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect); void addOverrideScalingModeLocked(Transaction* transaction, int32_t layerId, int32_t overrideScalingMode); void addSurfaceChangesLocked(Transaction* transaction, const layer_state_t& state); diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index e1c0fd340d..a5bf9c16ca 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -101,7 +101,6 @@ LayerProtoParser::Layer* LayerProtoParser::generateLayer(const LayerProto& layer layerProto.requested_position().y()}; layer->size = {layerProto.size().w(), layerProto.size().h()}; layer->crop = generateRect(layerProto.crop()); - layer->finalCrop = generateRect(layerProto.final_crop()); layer->isOpaque = layerProto.is_opaque(); layer->invalidate = layerProto.invalidate(); layer->dataspace = layerProto.dataspace(); @@ -299,8 +298,7 @@ std::string LayerProtoParser::Layer::to_string() const { z, static_cast(position.x), static_cast(position.y), size.x, size.y); - StringAppendF(&result, "crop=%s, finalCrop=%s, ", crop.to_string().c_str(), - finalCrop.to_string().c_str()); + StringAppendF(&result, "crop=%s, ", crop.to_string().c_str()); StringAppendF(&result, "isOpaque=%1d, invalidate=%1d, ", isOpaque, invalidate); StringAppendF(&result, "dataspace=%s, ", dataspace.c_str()); StringAppendF(&result, "defaultPixelFormat=%s, ", pixelFormat.c_str()); diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index 360e5997d1..b1610cf9ce 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -92,7 +92,6 @@ public: float2 requestedPosition; int2 size; LayerProtoParser::Rect crop; - LayerProtoParser::Rect finalCrop; bool isOpaque; bool invalidate; std::string dataspace; diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index 7f882daa60..2a096345af 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -41,7 +41,7 @@ message LayerProto { // The layer's crop in it's own bounds. optional RectProto crop = 14; // The layer's crop in it's parent's bounds. - optional RectProto final_crop = 15; + optional RectProto final_crop = 15 [deprecated=true]; optional bool is_opaque = 16; optional bool invalidate = 17; optional string dataspace = 18; diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter index 1319e12493..34d0fd75f9 100644 --- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter +++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter @@ -1,5 +1,5 @@ { "presubmit": { - "filter": "CredentialsTest.*:LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*:SurfaceInterceptorTest.*:-CropLatchingTest.FinalCropLatchingBufferOldSize" + "filter": "CredentialsTest.*:LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*:SurfaceInterceptorTest.*" } } diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index 8ac2c87b9e..740d2fa302 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -167,7 +167,6 @@ public: bool alphaUpdateFound(const SurfaceChange& change, bool foundAlpha); bool layerUpdateFound(const SurfaceChange& change, bool foundLayer); bool cropUpdateFound(const SurfaceChange& change, bool foundCrop); - bool finalCropUpdateFound(const SurfaceChange& change, bool foundFinalCrop); bool matrixUpdateFound(const SurfaceChange& change, bool foundMatrix); bool scalingModeUpdateFound(const SurfaceChange& change, bool foundScalingMode); bool transparentRegionHintUpdateFound(const SurfaceChange& change, bool foundTransparentRegion); @@ -199,7 +198,6 @@ public: void alphaUpdate(Transaction&); void layerUpdate(Transaction&); void cropUpdate(Transaction&); - void finalCropUpdate(Transaction&); void matrixUpdate(Transaction&); void overrideScalingModeUpdate(Transaction&); void transparentRegionHintUpdate(Transaction&); @@ -323,10 +321,6 @@ void SurfaceInterceptorTest::cropUpdate(Transaction& t) { t.setCrop_legacy(mBGSurfaceControl, CROP_UPDATE); } -void SurfaceInterceptorTest::finalCropUpdate(Transaction& t) { - t.setFinalCrop_legacy(mBGSurfaceControl, CROP_UPDATE); -} - void SurfaceInterceptorTest::matrixUpdate(Transaction& t) { t.setMatrix(mBGSurfaceControl, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2, M_SQRT1_2); } @@ -377,7 +371,6 @@ void SurfaceInterceptorTest::runAllUpdates() { runInTransaction(&SurfaceInterceptorTest::alphaUpdate); runInTransaction(&SurfaceInterceptorTest::layerUpdate); runInTransaction(&SurfaceInterceptorTest::cropUpdate); - runInTransaction(&SurfaceInterceptorTest::finalCropUpdate); runInTransaction(&SurfaceInterceptorTest::matrixUpdate); runInTransaction(&SurfaceInterceptorTest::overrideScalingModeUpdate); runInTransaction(&SurfaceInterceptorTest::transparentRegionHintUpdate); @@ -460,20 +453,6 @@ bool SurfaceInterceptorTest::cropUpdateFound(const SurfaceChange& change, bool f return foundCrop; } -bool SurfaceInterceptorTest::finalCropUpdateFound(const SurfaceChange& change, - bool foundFinalCrop) { - bool hasLeft(change.final_crop().rectangle().left() == CROP_UPDATE.left); - bool hasTop(change.final_crop().rectangle().top() == CROP_UPDATE.top); - bool hasRight(change.final_crop().rectangle().right() == CROP_UPDATE.right); - bool hasBottom(change.final_crop().rectangle().bottom() == CROP_UPDATE.bottom); - if (hasLeft && hasRight && hasTop && hasBottom && !foundFinalCrop) { - foundFinalCrop = true; - } else if (hasLeft && hasRight && hasTop && hasBottom && foundFinalCrop) { - [] () { FAIL(); }(); - } - return foundFinalCrop; -} - bool SurfaceInterceptorTest::matrixUpdateFound(const SurfaceChange& change, bool foundMatrix) { bool hasSx((float)change.matrix().dsdx() == (float)M_SQRT1_2); bool hasTx((float)change.matrix().dtdx() == (float)M_SQRT1_2); @@ -593,9 +572,6 @@ bool SurfaceInterceptorTest::surfaceUpdateFound(const Trace& trace, case SurfaceChange::SurfaceChangeCase::kCrop: foundUpdate = cropUpdateFound(change, foundUpdate); break; - case SurfaceChange::SurfaceChangeCase::kFinalCrop: - foundUpdate = finalCropUpdateFound(change, foundUpdate); - break; case SurfaceChange::SurfaceChangeCase::kMatrix: foundUpdate = matrixUpdateFound(change, foundUpdate); break; @@ -636,7 +612,6 @@ void SurfaceInterceptorTest::assertAllUpdatesFound(const Trace& trace) { ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kAlpha)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kLayer)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kCrop)); - ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kFinalCrop)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kMatrix)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kOverrideScalingMode)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kTransparentRegionHint)); @@ -755,11 +730,6 @@ TEST_F(SurfaceInterceptorTest, InterceptCropUpdateWorks) { captureTest(&SurfaceInterceptorTest::cropUpdate, SurfaceChange::SurfaceChangeCase::kCrop); } -TEST_F(SurfaceInterceptorTest, InterceptFinalCropUpdateWorks) { - captureTest(&SurfaceInterceptorTest::finalCropUpdate, - SurfaceChange::SurfaceChangeCase::kFinalCrop); -} - TEST_F(SurfaceInterceptorTest, InterceptMatrixUpdateWorks) { captureTest(&SurfaceInterceptorTest::matrixUpdate, SurfaceChange::SurfaceChangeCase::kMatrix); } diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 4ab4fec267..ed1529b37b 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -1759,168 +1759,6 @@ TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow_BufferState) { } } -TEST_F(LayerTransactionTest, SetFinalCropBasic_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - const Rect crop(8, 8, 24, 24); - - // same as in SetCropBasic - Transaction().setFinalCrop_legacy(layer, crop).apply(); - auto shot = screenshot(); - shot->expectColor(crop, Color::RED); - shot->expectBorder(crop, Color::BLACK); -} - -TEST_F(LayerTransactionTest, SetFinalCropEmpty_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // same as in SetCropEmpty - { - SCOPED_TRACE("empty rect"); - Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 8, 8)).apply(); - screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - { - SCOPED_TRACE("negative rect"); - Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 0, 0)).apply(); - screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } -} - -TEST_F(LayerTransactionTest, SetFinalCropOutOfBounds_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // same as in SetCropOutOfBounds - Transaction().setFinalCrop_legacy(layer, Rect(-128, -64, 128, 64)).apply(); - auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); -} - -TEST_F(LayerTransactionTest, SetFinalCropWithTranslation_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // final crop is applied post-translation - Transaction().setPosition(layer, 16, 16).setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)).apply(); - auto shot = screenshot(); - shot->expectColor(Rect(16, 16, 24, 24), Color::RED); - shot->expectBorder(Rect(16, 16, 24, 24), Color::BLACK); -} - -TEST_F(LayerTransactionTest, SetFinalCropWithScale_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // final crop is not affected by matrix - Transaction() - .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f) - .setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)) - .apply(); - auto shot = screenshot(); - shot->expectColor(Rect(8, 8, 24, 24), Color::RED); - shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK); -} - -TEST_F(LayerTransactionTest, SetFinalCropWithResize_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // same as in SetCropWithResize - Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); - { - SCOPED_TRACE("resize pending"); - auto shot = screenshot(); - shot->expectColor(Rect(8, 8, 24, 24), Color::RED); - shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK); - } - - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); - { - SCOPED_TRACE("resize applied"); - auto shot = screenshot(); - shot->expectColor(Rect(8, 8, 16, 16), Color::RED); - shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK); - } -} - -TEST_F(LayerTransactionTest, SetFinalCropWithNextResize_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // same as in SetCropWithNextResize - Transaction() - .setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)) - .setGeometryAppliesWithResize(layer) - .apply(); - { - SCOPED_TRACE("waiting for next resize"); - screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - Transaction().setFinalCrop_legacy(layer, Rect(4, 4, 12, 12)).apply(); - { - SCOPED_TRACE("pending final crop modified"); - screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - Transaction().setSize(layer, 16, 16).apply(); - { - SCOPED_TRACE("resize pending"); - screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - // finally resize - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); - { - SCOPED_TRACE("new final crop applied"); - auto shot = screenshot(); - shot->expectColor(Rect(4, 4, 12, 12), Color::RED); - shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK); - } -} - -TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // same as in SetCropWithNextResizeScaleToWindow - Transaction() - .setFinalCrop_legacy(layer, Rect(4, 4, 12, 12)) - .setSize(layer, 16, 16) - .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) - .setGeometryAppliesWithResize(layer) - .apply(); - { - SCOPED_TRACE("new final crop pending"); - auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 16, 16), Color::RED); - shot->expectBorder(Rect(0, 0, 16, 16), Color::BLACK); - } - - // XXX final crop is never latched without other geometry change (b/69315677) - Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply(); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); - Transaction().setPosition(layer, 0, 0).apply(); - { - SCOPED_TRACE("new final crop applied"); - auto shot = screenshot(); - shot->expectColor(Rect(4, 4, 12, 12), Color::RED); - shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK); - } -} - TEST_F(LayerTransactionTest, SetBufferBasic_BufferState) { sp layer; ASSERT_NO_FATAL_FAILURE( @@ -2346,7 +2184,6 @@ protected: t.setSize(mFGSurfaceControl, 64, 64); t.setPosition(mFGSurfaceControl, 64, 64); t.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 64, 64)); - t.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, -1, -1)); }); EXPECT_INITIAL_STATE("After restoring initial state"); @@ -2375,43 +2212,6 @@ protected: } }; -// In this test we ensure that setGeometryAppliesWithResize actually demands -// a buffer of the new size, and not just any size. -TEST_F(CropLatchingTest, FinalCropLatchingBufferOldSize) { - EXPECT_INITIAL_STATE("before anything"); - // Normally the crop applies immediately even while a resize is pending. - asTransaction([&](Transaction& t) { - t.setSize(mFGSurfaceControl, 128, 128); - t.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); - }); - - EXPECT_CROPPED_STATE("after setting crop (without geometryAppliesWithResize)"); - - restoreInitialState(); - - // In order to prepare to submit a buffer at the wrong size, we acquire it prior to - // initiating the resize. - lockAndFillFGBuffer(); - - asTransaction([&](Transaction& t) { - t.setSize(mFGSurfaceControl, 128, 128); - t.setGeometryAppliesWithResize(mFGSurfaceControl); - t.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); - }); - - EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)"); - - // We now submit our old buffer, at the old size, and ensure it doesn't - // trigger geometry latching. - unlockFGBuffer(); - - EXPECT_INITIAL_STATE("after unlocking FG buffer (with geometryAppliesWithResize)"); - - completeFGResize(); - - EXPECT_CROPPED_STATE("after the resize finishes"); -} - TEST_F(LayerUpdateTest, DeferredTransactionTest) { sp sc; { @@ -2588,22 +2388,6 @@ TEST_F(ChildLayerTest, ChildLayerCropping) { } } -TEST_F(ChildLayerTest, ChildLayerFinalCropping) { - asTransaction([&](Transaction& t) { - t.show(mChild); - t.setPosition(mChild, 0, 0); - t.setPosition(mFGSurfaceControl, 0, 0); - t.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5)); - }); - - { - ScreenCapture::captureScreen(&mCapture); - mCapture->expectChildColor(0, 0); - mCapture->expectChildColor(4, 4); - mCapture->expectBGColor(5, 5); - } -} - TEST_F(ChildLayerTest, ChildLayerConstraints) { asTransaction([&](Transaction& t) { t.show(mChild); diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 7fafab9302..356a880b6e 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -634,40 +634,6 @@ TEST_F(TransactionTest, LayerCrop) { EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); } -TEST_F(TransactionTest, LayerFinalCrop) { - // TODO: Add scaling to confirm that crop happens in display space? - { - TransactionScope ts(*sFakeComposer); - Rect cropRect(32, 32, 32 + 64, 32 + 64); - ts.setFinalCrop_legacy(mFGSurfaceControl, cropRect); - } - ASSERT_EQ(2, sFakeComposer->getFrameCount()); - - // In display space we are cropping with [32, 32, 96, 96] against display rect - // [64, 64, 128, 128]. Should yield display rect [64, 64, 96, 96] - auto referenceFrame = mBaseFrame; - referenceFrame[FG_LAYER].mSourceCrop = hwc_frect_t{0.f, 0.f, 32.f, 32.f}; - referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 32, 64 + 32}; - - EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); -} - -TEST_F(TransactionTest, LayerFinalCropEmpty) { - // TODO: Add scaling to confirm that crop happens in display space? - { - TransactionScope ts(*sFakeComposer); - Rect cropRect(16, 16, 32, 32); - ts.setFinalCrop_legacy(mFGSurfaceControl, cropRect); - } - ASSERT_EQ(2, sFakeComposer->getFrameCount()); - - // In display space we are cropping with [16, 16, 32, 32] against display rect - // [64, 64, 128, 128]. The intersection is empty and only the background layer is composited. - std::vector referenceFrame(1); - referenceFrame[BG_LAYER] = mBaseFrame[BG_LAYER]; - EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); -} - TEST_F(TransactionTest, LayerSetLayer) { { TransactionScope ts(*sFakeComposer); @@ -992,22 +958,6 @@ TEST_F(ChildLayerTest, Cropping) { EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); } -TEST_F(ChildLayerTest, FinalCropping) { - { - TransactionScope ts(*sFakeComposer); - ts.show(mChild); - ts.setPosition(mChild, 0, 0); - ts.setPosition(mFGSurfaceControl, 0, 0); - ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5)); - } - auto referenceFrame = mBaseFrame; - referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 0 + 5, 0 + 5}; - referenceFrame[FG_LAYER].mSourceCrop = hwc_frect_t{0.f, 0.f, 5.f, 5.f}; - referenceFrame[CHILD_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 0 + 5, 0 + 5}; - referenceFrame[CHILD_LAYER].mSourceCrop = hwc_frect_t{0.f, 0.f, 5.f, 5.f}; - EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); -} - TEST_F(ChildLayerTest, Constraints) { { TransactionScope ts(*sFakeComposer); @@ -1354,7 +1304,6 @@ protected: ts.setSize(mFGSurfaceControl, 64, 64); ts.setPosition(mFGSurfaceControl, 64, 64); ts.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 64, 64)); - ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, -1, -1)); } }; @@ -1425,111 +1374,6 @@ TEST_F(LatchingTest, CropLatching) { EXPECT_TRUE(framesAreSame(referenceFrame2, sFakeComposer->getLatestFrame())); } -TEST_F(LatchingTest, FinalCropLatching) { - // Normally the crop applies immediately even while a resize is pending. - { - TransactionScope ts(*sFakeComposer); - ts.setSize(mFGSurfaceControl, 128, 128); - ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); - } - - auto referenceFrame1 = mBaseFrame; - referenceFrame1[FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 127, 127}; - referenceFrame1[FG_LAYER].mSourceCrop = - hwc_frect_t{0.f, 0.f, static_cast(127 - 64), static_cast(127 - 64)}; - EXPECT_TRUE(framesAreSame(referenceFrame1, sFakeComposer->getLatestFrame())); - - restoreInitialState(); - - { - TransactionScope ts(*sFakeComposer); - ts.setSize(mFGSurfaceControl, 128, 128); - ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); - } - EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); - - completeFGResize(); - - auto referenceFrame2 = mBaseFrame; - referenceFrame2[FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 127, 127}; - referenceFrame2[FG_LAYER].mSourceCrop = - hwc_frect_t{0.f, 0.f, static_cast(127 - 64), static_cast(127 - 64)}; - referenceFrame2[FG_LAYER].mSwapCount++; - EXPECT_TRUE(framesAreSame(referenceFrame2, sFakeComposer->getLatestFrame())); -} - -// In this test we ensure that setGeometryAppliesWithResize actually demands -// a buffer of the new size, and not just any size. -TEST_F(LatchingTest, FinalCropLatchingBufferOldSize) { - // Normally the crop applies immediately even while a resize is pending. - { - TransactionScope ts(*sFakeComposer); - ts.setSize(mFGSurfaceControl, 128, 128); - ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); - } - - auto referenceFrame1 = mBaseFrame; - referenceFrame1[FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 127, 127}; - referenceFrame1[FG_LAYER].mSourceCrop = - hwc_frect_t{0.f, 0.f, static_cast(127 - 64), static_cast(127 - 64)}; - EXPECT_TRUE(framesAreSame(referenceFrame1, sFakeComposer->getLatestFrame())); - - restoreInitialState(); - - // In order to prepare to submit a buffer at the wrong size, we acquire it prior to - // initiating the resize. - lockAndFillFGBuffer(); - - { - TransactionScope ts(*sFakeComposer); - ts.setSize(mFGSurfaceControl, 128, 128); - ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); - } - EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); - - // We now submit our old buffer, at the old size, and ensure it doesn't - // trigger geometry latching. - unlockFGBuffer(); - - auto referenceFrame2 = mBaseFrame; - referenceFrame2[FG_LAYER].mSwapCount++; - EXPECT_TRUE(framesAreSame(referenceFrame2, sFakeComposer->getLatestFrame())); - - completeFGResize(); - auto referenceFrame3 = referenceFrame2; - referenceFrame3[FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 127, 127}; - referenceFrame3[FG_LAYER].mSourceCrop = - hwc_frect_t{0.f, 0.f, static_cast(127 - 64), static_cast(127 - 64)}; - referenceFrame3[FG_LAYER].mSwapCount++; - EXPECT_TRUE(framesAreSame(referenceFrame3, sFakeComposer->getLatestFrame())); -} - -TEST_F(LatchingTest, FinalCropLatchingRegressionForb37531386) { - // In this scenario, we attempt to set the final crop a second time while the resize - // is still pending, and ensure we are successful. Success meaning the second crop - // is the one which eventually latches and not the first. - { - TransactionScope ts(*sFakeComposer); - ts.setSize(mFGSurfaceControl, 128, 128); - ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127)); - } - - { - TransactionScope ts(*sFakeComposer); - ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, -1, -1)); - } - EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); - - completeFGResize(); - - auto referenceFrame = mBaseFrame; - referenceFrame[FG_LAYER].mSwapCount++; - EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); -} - } // namespace int main(int argc, char** argv) { -- cgit v1.2.3-59-g8ed1b From 1be50b50ab7fda600a7939a531d22909075e553b Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Wed, 29 Aug 2018 10:44:48 -0700 Subject: surfaceflinger: use Vulkan coordinate system In Vulkan coordinate system, (0, 0) always maps to memory address 0. In GL coordinate system, (0, 0) maps to the bottom-left corner. The two agree when doing offscreen rendering. But when rendering to a window, GL maps (0, 0) to memory address (winHeight-1)*rowStride, because that is where the bottom-left pixel is. Let's pick the simpler one for RenderEngine in preparation for multiple backends. As a result, we don't need yswap when rendering to offscreen buffers (it is hidden behind the RenderEngine API). It also makes no sense to flip Y coordinate for both vertex postions and the viewing volume. Test: chrome, youtube, camera, screen rotation, screenshots, recents Change-Id: I6d6317bac3de6f208700a67e518011362c600ced --- libs/gui/GLConsumer.cpp | 8 ++++---- services/surfaceflinger/BufferLayer.cpp | 1 + services/surfaceflinger/DisplayDevice.cpp | 3 +-- services/surfaceflinger/Layer.cpp | 4 ---- .../RenderEngine/gl/GLES20RenderEngine.cpp | 20 +++++++++----------- .../RenderEngine/gl/GLES20RenderEngine.h | 6 ++++-- .../RenderEngine/include/renderengine/RenderEngine.h | 5 +++-- services/surfaceflinger/SurfaceFlinger.cpp | 10 +++------- services/surfaceflinger/SurfaceFlinger.h | 2 +- .../unittests/mock/RenderEngine/MockRenderEngine.h | 4 ++-- 10 files changed, 28 insertions(+), 35 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp index 5532db43ad..faf02f3b53 100644 --- a/libs/gui/GLConsumer.cpp +++ b/libs/gui/GLConsumer.cpp @@ -834,10 +834,10 @@ void GLConsumer::computeTransformMatrix(float outTransform[16], xform = crop * xform; } - // SurfaceFlinger expects the top of its window textures to be at a Y - // coordinate of 0, so GLConsumer must behave the same way. We don't - // want to expose this to applications, however, so we must add an - // additional vertical flip to the transform after all the other transforms. + // GLConsumer uses the GL convention where (0, 0) is the bottom-left + // corner and (1, 1) is the top-right corner. Add an additional vertical + // flip after all other transforms to map from GL convention to buffer + // queue memory layout, where (0, 0) is the top-left corner. xform = mtxFlipV * xform; memcpy(outTransform, xform.asArray(), sizeof(xform)); diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 6cfee3f1bf..4da71cc315 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -609,6 +609,7 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT // TODO: we probably want to generate the texture coords with the mesh // here we assume that we only have 4 vertices renderengine::Mesh::VertexArray texCoords(getBE().mMesh.getTexCoordArray()); + // flip texcoords vertically because BufferLayerConsumer expects them to be in GL convention texCoords[0] = vec2(left, 1.0f - top); texCoords[1] = vec2(left, 1.0f - bottom); texCoords[2] = vec2(right, 1.0f - bottom); diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 7fe18d898b..3eb0a92eb4 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -386,8 +386,7 @@ void DisplayDevice::setViewportAndProjection() const { size_t w = mDisplayWidth; size_t h = mDisplayHeight; Rect sourceCrop(0, 0, w, h); - mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, h, - false, ui::Transform::ROT_0); + mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, ui::Transform::ROT_0); } const sp& DisplayDevice::getClientTargetAcquireFence() const { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e4f8e7da2f..ecab4e40df 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -791,7 +791,6 @@ void Layer::computeGeometry(const RenderArea& renderArea, bool useIdentityTransform) const { const Layer::State& s(getDrawingState()); const ui::Transform renderAreaTransform(renderArea.getTransform()); - const uint32_t height = renderArea.getHeight(); FloatRect win = computeBounds(); vec2 lt = vec2(win.left, win.top); @@ -820,9 +819,6 @@ void Layer::computeGeometry(const RenderArea& renderArea, 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::isSecure() const { diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp index e0f1850faa..42d488792f 100644 --- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp @@ -160,21 +160,15 @@ size_t GLES20RenderEngine::getMaxViewportDims() const { } void GLES20RenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, - size_t hwh, bool yswap, ui::Transform::orientation_flags rotation) { int32_t l = sourceCrop.left; int32_t r = sourceCrop.right; - - // In GL, (0, 0) is the bottom-left corner, so flip y coordinates - int32_t t = hwh - sourceCrop.top; - int32_t b = hwh - sourceCrop.bottom; - - mat4 m; - if (yswap) { - m = mat4::ortho(l, r, t, b, 0, 1); - } else { - m = mat4::ortho(l, r, b, t, 0, 1); + int32_t b = sourceCrop.bottom; + int32_t t = sourceCrop.top; + if (mRenderToFbo) { + std::swap(t, b); } + mat4 m = mat4::ortho(l, r, b, t, 0, 1); // Apply custom rotation to the projection. float rot90InRadians = 2.0f * static_cast(M_PI) / 4.0f; @@ -284,9 +278,13 @@ void GLES20RenderEngine::bindImageAsFramebuffer(EGLImageKHR image, uint32_t* tex *status = glCheckFramebufferStatus(GL_FRAMEBUFFER); *texName = tname; *fbName = name; + + mRenderToFbo = true; } void GLES20RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName) { + mRenderToFbo = false; + glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &fbName); glDeleteTextures(1, &texName); diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h index c830184bfa..e6a7a004a0 100644 --- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h @@ -62,8 +62,8 @@ public: protected: virtual void dump(String8& result); - virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, - bool yswap, ui::Transform::orientation_flags rotation); + virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, + ui::Transform::orientation_flags rotation); virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture, const half4& color) override; @@ -108,6 +108,8 @@ private: // with PQ or HLG transfer function. bool isHdrDataSpace(const ui::Dataspace dataSpace) const; bool needsXYZTransformMatrix() const; + + bool mRenderToFbo = false; }; } // namespace gl diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h index c532adc3ac..a363cd4a43 100644 --- a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h @@ -96,14 +96,15 @@ public: virtual void deleteTextures(size_t count, uint32_t const* names) = 0; virtual void bindExternalTextureImage(uint32_t texName, const renderengine::Image& image) = 0; virtual void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) = 0; + // When binding a native buffer, it must be done before setViewportAndProjection virtual void bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer, BindNativeBufferAsFramebuffer* bindHelper) = 0; virtual void unbindNativeBufferAsFrameBuffer(BindNativeBufferAsFramebuffer* bindHelper) = 0; // set-up virtual void checkErrors() const; - virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, - bool yswap, ui::Transform::orientation_flags rotation) = 0; + virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, + ui::Transform::orientation_flags rotation) = 0; virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture, const half4& color) = 0; virtual void setupLayerTexturing(const Texture& texture) = 0; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 3529741d98..633510f9f4 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5326,15 +5326,12 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, } void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, - TraverseLayersFunction traverseLayers, bool yswap, + TraverseLayersFunction traverseLayers, bool useIdentityTransform) { ATRACE_CALL(); auto& engine(getRenderEngine()); - // get screen geometry - const auto raHeight = renderArea.getHeight(); - const auto reqWidth = renderArea.getReqWidth(); const auto reqHeight = renderArea.getReqHeight(); const auto sourceCrop = renderArea.getSourceCrop(); @@ -5348,8 +5345,7 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, engine.checkErrors(); // set-up our viewport - engine.setViewportAndProjection(reqWidth, reqHeight, sourceCrop, raHeight, yswap, - rotation); + engine.setViewportAndProjection(reqWidth, reqHeight, sourceCrop, rotation); engine.disableTexturing(); const float alpha = RenderArea::getCaptureFillValue(renderArea.getCaptureFill()); @@ -5395,7 +5391,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, // via an FBO, which means we didn't have to create // an EGLSurface and therefore we're not // dependent on the context's EGLConfig. - renderScreenImplLocked(renderArea, traverseLayers, true, useIdentityTransform); + renderScreenImplLocked(renderArea, traverseLayers, useIdentityTransform); if (DEBUG_SCREENSHOTS) { getRenderEngine().finish(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 863ab10eb4..898bec7948 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -581,7 +581,7 @@ private: void startBootAnim(); void renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, - bool yswap, bool useIdentityTransform); + bool useIdentityTransform); status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers, sp* outBuffer, bool useIdentityTransform); diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h index bf3c09af07..7d504c517f 100644 --- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h +++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h @@ -55,8 +55,8 @@ public: MOCK_METHOD2(bindExternalTextureImage, void(uint32_t, const renderengine::Image&)); MOCK_METHOD5(readPixels, void(size_t, size_t, size_t, size_t, uint32_t*)); MOCK_CONST_METHOD0(checkErrors, void()); - MOCK_METHOD6(setViewportAndProjection, - void(size_t, size_t, Rect, size_t, bool, ui::Transform::orientation_flags)); + MOCK_METHOD4(setViewportAndProjection, + void(size_t, size_t, Rect, ui::Transform::orientation_flags)); MOCK_METHOD4(setupLayerBlending, void(bool, bool, bool, const half4&)); MOCK_METHOD1(setupLayerTexturing, void(const Texture&)); MOCK_METHOD0(setupLayerBlackedOut, void()); -- cgit v1.2.3-59-g8ed1b From 33119ad2621ac68b204e07b487ec4610760d1eec Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Wed, 29 Aug 2018 10:45:53 -0700 Subject: surfaceflinger: remove some unused Layer methods Remove unused void draw(const RenderArea& renderArea); void clearWithOpenGL(const RenderArea& renderArea) const; from class Layer. Test: builds Change-Id: I5359c9260c060a09d0b0d94412f386c64065e6ed --- services/surfaceflinger/Layer.cpp | 9 --------- services/surfaceflinger/Layer.h | 3 --- 2 files changed, 12 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e4f8e7da2f..b3c6af3a02 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -699,10 +699,6 @@ void Layer::draw(const RenderArea& renderArea, bool useIdentityTransform) { onDraw(renderArea, Region(renderArea.getBounds()), useIdentityTransform); } -void Layer::draw(const RenderArea& renderArea) { - onDraw(renderArea, Region(renderArea.getBounds()), false); -} - void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green, float blue, float alpha) const { auto& engine(mFlinger->getRenderEngine()); @@ -711,11 +707,6 @@ void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green engine.drawMesh(getBE().mMesh); } -void Layer::clearWithOpenGL(const RenderArea& renderArea) const { - getBE().compositionInfo.firstClear = true; - computeGeometry(renderArea, getBE().mMesh, false); -} - void Layer::setCompositionType(int32_t displayId, HWC2::Composition type, bool /*callIntoHwc*/) { if (getBE().mHwcLayers.count(displayId) == 0) { ALOGE("setCompositionType called without a valid HWC layer"); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 80152ad5cb..786ece6f2c 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -414,7 +414,6 @@ public: */ void draw(const RenderArea& renderArea, const Region& clip); void draw(const RenderArea& renderArea, bool useIdentityTransform); - void draw(const RenderArea& renderArea); /* * doTransaction - process the transaction. This is a good place to figure @@ -512,8 +511,6 @@ public: // ----------------------------------------------------------------------- - void clearWithOpenGL(const RenderArea& renderArea) const; - inline const State& getDrawingState() const { return mDrawingState; } inline const State& getCurrentState() const { return mCurrentState; } inline State& getCurrentState() { return mCurrentState; } -- cgit v1.2.3-59-g8ed1b From b416efdeab0d399f8922ff2d69d86c9be3201238 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Thu, 6 Sep 2018 21:01:59 +0000 Subject: Don't fully qualify Layer::State in Layer.cpp Style justification at go/totw/151. Test: SurfaceFlinger_test didn't break. Change-Id: Ie4ebbbe7939de1d89e9a0b724321da3625e9ffa7 --- services/surfaceflinger/Layer.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 29de50ccd9..a1e45b076c 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -284,7 +284,7 @@ static FloatRect reduce(const FloatRect& win, const Region& exclude) { } Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { - const Layer::State& s(getDrawingState()); + const State& s(getDrawingState()); Rect win(getActiveWidth(s), getActiveHeight(s)); Rect crop = getCrop(s); @@ -319,12 +319,12 @@ Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { } FloatRect Layer::computeBounds() const { - const Layer::State& s(getDrawingState()); + const State& s(getDrawingState()); return computeBounds(getActiveTransparentRegion(s)); } FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const { - const Layer::State& s(getDrawingState()); + const State& s(getDrawingState()); Rect win(getActiveWidth(s), getActiveHeight(s)); Rect crop = getCrop(s); @@ -762,7 +762,7 @@ void Layer::computeGeometry(const RenderArea& renderArea, } bool Layer::isSecure() const { - const Layer::State& s(mDrawingState); + const State& s(mDrawingState); return (s.flags & layer_state_t::eLayerSecure); } @@ -885,7 +885,7 @@ bool Layer::applyPendingStates(State* stateToCommit) { } uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { - const Layer::State& s(getDrawingState()); + const State& s(getDrawingState()); const bool sizeChanged = (stateToCommit->requested_legacy.w != s.requested_legacy.w) || (stateToCommit->requested_legacy.h != s.requested_legacy.h); @@ -941,7 +941,7 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { // latching configuration. See Layer.h for a detailed discussion of // how geometry latching is controlled. if (!(flags & eDontUpdateGeometryState)) { - Layer::State& editCurrentState(getCurrentState()); + State& editCurrentState(getCurrentState()); // If mFreezeGeometryUpdates is true we are in the setGeometryAppliesWithResize // mode, which causes attributes which normally latch regardless of scaling mode, @@ -974,14 +974,14 @@ uint32_t Layer::doTransaction(uint32_t flags) { ATRACE_CALL(); pushPendingState(); - Layer::State c = getCurrentState(); + State c = getCurrentState(); if (!applyPendingStates(&c)) { return 0; } flags = doTransactionResize(flags, &c); - const Layer::State& s(getDrawingState()); + const State& s(getDrawingState()); if (getActiveGeometry(c) != getActiveGeometry(s)) { // invalidate and recompute the visible regions if needed @@ -1272,7 +1272,7 @@ void Layer::deferTransactionUntil_legacy(const sp& barrierHandle, uint6 // ---------------------------------------------------------------------------- bool Layer::isHiddenByPolicy() const { - const Layer::State& s(mDrawingState); + const State& s(mDrawingState); const auto& parent = mDrawingParent.promote(); if (parent != nullptr && parent->isHiddenByPolicy()) { return true; @@ -1315,7 +1315,7 @@ void Layer::updateTransformHint(const sp& display) const { // TODO(marissaw): add new layer state info to layer debugging LayerDebugInfo Layer::getLayerDebugInfo() const { LayerDebugInfo info; - const Layer::State& ds = getDrawingState(); + const State& ds = getDrawingState(); info.mName = getName(); sp parent = getParent(); info.mParentName = (parent == nullptr ? std::string("none") : parent->getName().string()); @@ -1392,7 +1392,7 @@ void Layer::miniDump(String8& result, int32_t displayId) const { result.appendFormat(" %s\n", name.string()); - const Layer::State& layerState(getDrawingState()); + const State& layerState(getDrawingState()); const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(displayId); if (layerState.zOrderRelativeOf != nullptr || mDrawingParent != nullptr) { result.appendFormat(" rel %6d | ", layerState.z); -- cgit v1.2.3-59-g8ed1b From c1498e6ed132092312e160ab00b0a2c8633611ed Mon Sep 17 00:00:00 2001 From: David Sodman Date: Wed, 12 Sep 2018 14:36:26 -0700 Subject: SF: Use getVisibleLayers... in doComposeSurfaces in b/114101122, it is discovered that there is a problem in indexing the SF mCompositionInfo by displayId because there are multiple displays that have the same id (-1). This change uses getVisibleLayersSortedByZ in doComposeSurfaces until we can fix the indexing of mCompositionInfo. Bug: 114101122 Test: run cts -m CtsViewTestCases, CtsMediaTestCases Change-Id: I90adb957c183400c396f25fa9583b668e1da8417 --- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 4 ++++ services/surfaceflinger/Layer.cpp | 4 ++++ services/surfaceflinger/Layer.h | 1 + services/surfaceflinger/LayerBE.h | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 23 +++++++++++----------- 5 files changed, 21 insertions(+), 13 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index d963ab61c0..6b56ca4e36 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -500,6 +500,8 @@ status_t HWComposer::prepare(DisplayDevice& display, validateChange(compositionInfo.compositionType, changedTypes[&*hwcLayer]); compositionInfo.compositionType = changedTypes[&*hwcLayer]; + compositionInfo.layer->mLayer->setCompositionType(displayId, + compositionInfo.compositionType, false); } switch (compositionInfo.compositionType) { @@ -520,6 +522,7 @@ status_t HWComposer::prepare(DisplayDevice& display, layerRequests[&*hwcLayer] == HWC2::LayerRequest::ClearClientTarget) { compositionInfo.hwc.clearClientTarget = true; + compositionInfo.layer->mLayer->setClearClientTarget(displayId, true); } else { if (layerRequests.count(&*hwcLayer) != 0) { LOG_DISPLAY_ERROR(displayId, @@ -527,6 +530,7 @@ status_t HWComposer::prepare(DisplayDevice& display, .c_str()); } compositionInfo.hwc.clearClientTarget = false; + compositionInfo.layer->mLayer->setClearClientTarget(displayId, false); } } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index a1e45b076c..03b63bda61 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -680,6 +680,10 @@ void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green engine.drawMesh(getBE().mMesh); } +void Layer::clearWithOpenGL(const RenderArea& renderArea) const { + clearWithOpenGL(renderArea, 0, 0, 0, 0); +} + void Layer::setCompositionType(int32_t displayId, HWC2::Composition type, bool /*callIntoHwc*/) { if (getBE().mHwcLayers.count(displayId) == 0) { ALOGE("setCompositionType called without a valid HWC layer"); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 9bd28b8acf..23201aacaf 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -503,6 +503,7 @@ public: } // ----------------------------------------------------------------------- + void clearWithOpenGL(const RenderArea& renderArea) const; inline const State& getDrawingState() const { return mDrawingState; } inline const State& getCurrentState() const { return mCurrentState; } diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index f5150a7feb..a8bdec44f2 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -94,8 +94,8 @@ public: void clear(renderengine::RenderEngine& renderEngine); renderengine::Mesh& getMesh() { return mMesh; } -private: Layer*const mLayer; +private: // The mesh used to draw the layer in GLES composition mode renderengine::Mesh mMesh; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9537cccee7..f17710ef0d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3218,30 +3218,29 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& display) { ALOGV("Rendering client layers"); const ui::Transform& displayTransform = display->getTransform(); bool firstLayer = true; - for (auto& compositionInfo : getBE().mCompositionInfo[displayId]) { - const Region bounds(display->bounds()); + for (auto& layer : display->getVisibleLayersSortedByZ()) { const Region clip(bounds.intersect( - displayTransform.transform(compositionInfo.layer->mLayer->visibleRegion))); - ALOGV("Layer: %s", compositionInfo.layerName.c_str()); + displayTransform.transform(layer->visibleRegion))); + ALOGV("Layer: %s", layer->getName().string()); + ALOGV(" Composition type: %s", to_string(layer->getCompositionType(displayId)).c_str()); if (!clip.isEmpty()) { - switch (compositionInfo.compositionType) { + switch (layer->getCompositionType(displayId)) { case HWC2::Composition::Cursor: case HWC2::Composition::Device: case HWC2::Composition::Sideband: case HWC2::Composition::SolidColor: { - const Layer::State& state(compositionInfo.layer->mLayer->getDrawingState()); - const bool opaque = compositionInfo.layer->mLayer->isOpaque(state) && - compositionInfo.layer->mLayer->getAlpha() == 1.0f; - if (compositionInfo.hwc.clearClientTarget && !firstLayer && opaque && - hasClientComposition) { + const Layer::State& state(layer->getDrawingState()); + if (layer->getClearClientTarget(displayId) && !firstLayer && + layer->isOpaque(state) && (layer->getAlpha() == 1.0f) && + hasClientComposition) { // never clear the very first layer since we're // guaranteed the FB is already cleared - compositionInfo.layer->clear(getRenderEngine()); + layer->clearWithOpenGL(renderArea); } break; } case HWC2::Composition::Client: { - compositionInfo.layer->mLayer->draw(renderArea, clip); + layer->draw(renderArea, clip); break; } default: -- cgit v1.2.3-59-g8ed1b From f1c675b33faeadc57f5d57a18d5e07bc644b0bad Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Wed, 12 Sep 2018 20:45:39 -0700 Subject: SF: Cleanups to use std::atomic/std::mutex A few places in the code used "volatile". This patch removes the volatile. In most of the cases, the volatile value was converted to a std::atomic value. The exception was Barrier where it was not actually necessary, but there I converted the code to use std::mutex. Bug: None Test: atest SurfaceFlinger_test CtsViewTestCases Change-Id: I7b4f5a7398a241db8201dc7f60d7c9cd41e32e1b --- services/surfaceflinger/Barrier.h | 30 +++++++++++--------------- services/surfaceflinger/BufferQueueLayer.cpp | 20 +++++++++-------- services/surfaceflinger/BufferQueueLayer.h | 4 ++-- services/surfaceflinger/Layer.cpp | 7 +++--- services/surfaceflinger/Layer.h | 7 +++--- services/surfaceflinger/SurfaceFlinger.cpp | 16 ++++++-------- services/surfaceflinger/SurfaceFlinger.h | 5 ++--- services/surfaceflinger/SurfaceInterceptor.cpp | 5 +++-- 8 files changed, 44 insertions(+), 50 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Barrier.h b/services/surfaceflinger/Barrier.h index 3e9d4433ad..97028a89fa 100644 --- a/services/surfaceflinger/Barrier.h +++ b/services/surfaceflinger/Barrier.h @@ -18,46 +18,40 @@ #define ANDROID_BARRIER_H #include -#include -#include +#include +#include namespace android { class Barrier { public: - inline Barrier() : state(CLOSED) { } - inline ~Barrier() { } - // Release any threads waiting at the Barrier. // Provides release semantics: preceding loads and stores will be visible // to other threads before they wake up. void open() { - Mutex::Autolock _l(lock); - state = OPENED; - cv.broadcast(); + std::lock_guard lock(mMutex); + mIsOpen = true; + mCondition.notify_all(); } // Reset the Barrier, so wait() will block until open() has been called. void close() { - Mutex::Autolock _l(lock); - state = CLOSED; + std::lock_guard lock(mMutex); + mIsOpen = false; } // Wait until the Barrier is OPEN. // Provides acquire semantics: no subsequent loads or stores will occur // until wait() returns. void wait() const { - Mutex::Autolock _l(lock); - while (state == CLOSED) { - cv.wait(lock); - } + std::unique_lock lock(mMutex); + mCondition.wait(lock, [this]() NO_THREAD_SAFETY_ANALYSIS { return mIsOpen; }); } private: - enum { OPENED, CLOSED }; - mutable Mutex lock; - mutable Condition cv; - volatile int state; + mutable std::mutex mMutex; + mutable std::condition_variable mCondition; + int mIsOpen GUARDED_BY(mMutex){false}; }; }; // namespace android diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 4839bfb45a..521cdbf579 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -207,8 +207,9 @@ bool BufferQueueLayer::getSidebandStreamChanged() const { } std::optional BufferQueueLayer::latchSidebandStream(bool& recomputeVisibleRegions) { - if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) { - // mSidebandStreamChanged was true + bool sidebandStreamChanged = true; + if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, false)) { + // mSidebandStreamChanged was changed to false // replicated in LayerBE until FE/BE is ready to be synchronized getBE().compositionInfo.hwc.sidebandStream = mConsumer->getSidebandStream(); if (getBE().compositionInfo.hwc.sidebandStream != nullptr) { @@ -259,7 +260,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t Mutex::Autolock lock(mQueueItemLock); mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber); mQueueItems.removeAt(0); - android_atomic_dec(&mQueuedFrames); + mQueuedFrames--; } return BAD_VALUE; } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) { @@ -270,7 +271,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t if (queuedBuffer) { Mutex::Autolock lock(mQueueItemLock); mQueueItems.clear(); - android_atomic_and(0, &mQueuedFrames); + mQueuedFrames = 0; mTimeStats.clearLayerRecord(getName().c_str()); } @@ -294,7 +295,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t while (mQueueItems[0].mFrameNumber != currentFrameNumber) { mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber); mQueueItems.removeAt(0); - android_atomic_dec(&mQueuedFrames); + mQueuedFrames--; } const std::string layerName(getName().c_str()); @@ -306,7 +307,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t // Decrement the queued-frames count. Signal another event if we // have more frames pending. - if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1) || mAutoRefresh) { + if ((queuedBuffer && mQueuedFrames.fetch_sub(1) > 1) || mAutoRefresh) { mFlinger->signalLayerUpdate(); } @@ -367,7 +368,7 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { } mQueueItems.push_back(item); - android_atomic_inc(&mQueuedFrames); + mQueuedFrames++; // Wake up any pending callbacks mLastFrameNumberReceived = item.mFrameNumber; @@ -404,8 +405,9 @@ void BufferQueueLayer::onFrameReplaced(const BufferItem& item) { } void BufferQueueLayer::onSidebandStreamChanged() { - if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) { - // mSidebandStreamChanged was false + bool sidebandStreamChanged = false; + if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, true)) { + // mSidebandStreamChanged was changed to true mFlinger->signalLayerUpdate(); } } diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 579ed81f7e..400f412d08 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -137,8 +137,8 @@ private: int mActiveBufferSlot; // thread-safe - volatile int32_t mQueuedFrames; - volatile int32_t mSidebandStreamChanged; // used like an atomic boolean + std::atomic mQueuedFrames{0}; + std::atomic mSidebandStreamChanged{false}; }; } // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 03b63bda61..19c84d0a85 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -62,12 +62,11 @@ namespace android { -int32_t Layer::sSequence = 1; +std::atomic Layer::sSequence{1}; Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags) : contentDirty(false), - sequence(uint32_t(android_atomic_inc(&sSequence))), mFlinger(flinger), mPremultipliedAlpha(true), mName(name), @@ -1019,11 +1018,11 @@ void Layer::commitTransaction(const State& stateToCommit) { } uint32_t Layer::getTransactionFlags(uint32_t flags) { - return android_atomic_and(~flags, &mTransactionFlags) & flags; + return mTransactionFlags.fetch_and(~flags) & flags; } uint32_t Layer::setTransactionFlags(uint32_t flags) { - return android_atomic_or(flags, &mTransactionFlags); + return mTransactionFlags.fetch_or(flags); } bool Layer::setPosition(float x, float y, bool immediate) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 3845b224de..74f0a63be8 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -73,7 +73,7 @@ class SurfaceInterceptor; // --------------------------------------------------------------------------- class Layer : public virtual RefBase { - static int32_t sSequence; + static std::atomic sSequence; public: friend class LayerBE; @@ -89,7 +89,7 @@ public: // Layer serial number. This gives layers an explicit ordering, so we // have a stable sort order when their layer stack and Z-order are // the same. - int32_t sequence; + int32_t sequence{sSequence++}; enum { // flags for doTransaction() eDontUpdateGeometryState = 0x00000001, @@ -271,6 +271,7 @@ public: virtual void useSurfaceDamage() {} virtual void useEmptyDamage() {} + uint32_t getTransactionFlags() const { return mTransactionFlags; } uint32_t getTransactionFlags(uint32_t flags); uint32_t setTransactionFlags(uint32_t flags); @@ -696,7 +697,7 @@ protected: // these are protected by an external lock State mCurrentState; State mDrawingState; - volatile int32_t mTransactionFlags; + std::atomic mTransactionFlags{0}; // Accessed from main thread and binder threads Mutex mPendingStateMutex; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index ad8a4dcf72..e2605b29f1 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -259,12 +259,10 @@ SurfaceFlingerBE::SurfaceFlingerBE() SurfaceFlinger::SurfaceFlinger(SurfaceFlinger::SkipInitializationTag) : BnSurfaceComposer(), - mTransactionFlags(0), mTransactionPending(false), mAnimTransactionPending(false), mLayersRemoved(false), mLayersAdded(false), - mRepaintEverything(0), mBootTime(systemTime()), mDisplayTokens(), mVisibleRegionsDirty(false), @@ -1468,7 +1466,7 @@ void SurfaceFlinger::updateVrFlinger() { resyncToHardwareVsync(false); - android_atomic_or(1, &mRepaintEverything); + mRepaintEverything = true; setTransactionFlags(eDisplayTransactionNeeded); } @@ -1527,7 +1525,7 @@ void SurfaceFlinger::handleMessageRefresh() { mRefreshPending = false; - const bool repaintEverything = android_atomic_and(0, &mRepaintEverything); + const bool repaintEverything = mRepaintEverything.exchange(false); preComposition(); rebuildLayerStacks(); calculateWorkingSet(); @@ -3355,11 +3353,11 @@ status_t SurfaceFlinger::removeLayerLocked(const Mutex&, const sp& layer, } uint32_t SurfaceFlinger::peekTransactionFlags() { - return android_atomic_release_load(&mTransactionFlags); + return mTransactionFlags; } uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags) { - return android_atomic_and(~flags, &mTransactionFlags) & flags; + return mTransactionFlags.fetch_and(~flags) & flags; } uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) { @@ -3368,7 +3366,7 @@ uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) { uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags, VSyncModulator::TransactionStart transactionStart) { - uint32_t old = android_atomic_or(flags, &mTransactionFlags); + uint32_t old = mTransactionFlags.fetch_or(flags); mVsyncModulator.setTransactionStart(transactionStart); if ((old & flags)==0) { // wake the server up signalTransaction(); @@ -4661,7 +4659,7 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, } result.appendFormat(" transaction-flags : %08x\n" " gpu_to_cpu_unsupported : %d\n", - mTransactionFlags, !mGpuToCpuSupported); + mTransactionFlags.load(), !mGpuToCpuSupported); if (display) { const auto activeConfig = getHwComposer().getActiveConfig(display->getId()); @@ -5172,7 +5170,7 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r } void SurfaceFlinger::repaintEverything() { - android_atomic_or(1, &mRepaintEverything); + mRepaintEverything = true; signalTransaction(); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index bfadf6ef8d..a300857749 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -794,7 +794,7 @@ private: // access must be protected by mStateLock mutable Mutex mStateLock; State mCurrentState{LayerVector::StateSet::Current}; - volatile int32_t mTransactionFlags; + std::atomic mTransactionFlags{0}; Condition mTransactionCV; bool mTransactionPending; bool mAnimTransactionPending; @@ -813,8 +813,7 @@ private: bool mLayersRemoved; bool mLayersAdded; - // access must be protected by mInvalidateLock - volatile int32_t mRepaintEverything; + std::atomic mRepaintEverything{false}; // helper methods void configureHwcCommonData(const CompositionInfo& compositionInfo) const; diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 0b4c6fcb79..57bda5a8c9 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -96,8 +96,9 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, const sp& layer) { Transaction* transaction(increment->mutable_transaction()); - transaction->set_synchronous(layer->mTransactionFlags & BnSurfaceComposer::eSynchronous); - transaction->set_animation(layer->mTransactionFlags & BnSurfaceComposer::eAnimation); + const uint32_t layerFlags = layer->getTransactionFlags(); + transaction->set_synchronous(layerFlags & BnSurfaceComposer::eSynchronous); + transaction->set_animation(layerFlags & BnSurfaceComposer::eAnimation); const int32_t layerId(getLayerId(layer)); addPositionLocked(transaction, layerId, layer->mCurrentState.active_legacy.transform.tx(), -- cgit v1.2.3-59-g8ed1b From 42ab75e0b89351f2346dd174b63f0445ceaf3ee3 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Wed, 12 Sep 2018 20:46:03 -0700 Subject: SF: Cleanup layer construction Introduce a LayerCreationArg parameter object, and modify all layer types to use it rather than having the same set of four arguments. Along the way simplify all constructors by moving to C++11 style default values defined in the header, and ensure the destructor is defined in the implementation file (as a default for most layer types, as only BufferLayer needs a non-default destructor). Using a uniform parameter object reduces the amount of work needed to maintain the upcoming factory interface. Test: Works on marlin. Test: atest libsurfaceflinger_unittest Change-Id: Ic09291fd3213ff980bfc600166bf798ba09daa32 --- services/surfaceflinger/BufferLayer.cpp | 20 ++++------- services/surfaceflinger/BufferLayer.h | 12 +++---- services/surfaceflinger/BufferQueueLayer.cpp | 21 ++--------- services/surfaceflinger/BufferQueueLayer.h | 16 ++++----- services/surfaceflinger/BufferStateLayer.cpp | 23 ++++++------ services/surfaceflinger/BufferStateLayer.h | 12 ++++--- services/surfaceflinger/ColorLayer.cpp | 15 ++++---- services/surfaceflinger/ColorLayer.h | 5 ++- services/surfaceflinger/ContainerLayer.cpp | 8 ++--- services/surfaceflinger/ContainerLayer.h | 5 ++- services/surfaceflinger/Layer.cpp | 40 ++++++--------------- services/surfaceflinger/Layer.h | 42 ++++++++++++++-------- services/surfaceflinger/SurfaceFlinger.cpp | 16 +++++---- .../tests/unittests/CompositionTest.cpp | 16 +++++---- 14 files changed, 110 insertions(+), 141 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 89394cd285..642ed2fefc 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -49,24 +49,16 @@ namespace android { -BufferLayer::BufferLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, - uint32_t w, uint32_t h, uint32_t flags) - : Layer(flinger, client, name, w, h, flags), - mTextureName(mFlinger->getNewTexture()), - mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), - mBufferLatched(false), - mRefreshPending(false) { - ALOGV("Creating Layer %s", name.string()); +BufferLayer::BufferLayer(const LayerCreationArgs& args) + : Layer(args), mTextureName(args.flinger->getNewTexture()) { + ALOGV("Creating Layer %s", args.name.string()); mTexture.init(renderengine::Texture::TEXTURE_EXTERNAL, mTextureName); - mPremultipliedAlpha = !(flags & ISurfaceComposerClient::eNonPremultiplied); + mPremultipliedAlpha = !(args.flags & ISurfaceComposerClient::eNonPremultiplied); - mPotentialCursor = flags & ISurfaceComposerClient::eCursorWindow; - mProtectedByApp = flags & ISurfaceComposerClient::eProtectedByApp; - - // drawing state & current state are identical - mDrawingState = mCurrentState; + mPotentialCursor = args.flags & ISurfaceComposerClient::eCursorWindow; + mProtectedByApp = args.flags & ISurfaceComposerClient::eProtectedByApp; } BufferLayer::~BufferLayer() { diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 45906ff223..92bf132f2a 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -39,6 +39,8 @@ #include #include +#include // For NATIVE_WINDOW_SCALING_MODE_FREEZE + #include #include #include @@ -47,9 +49,7 @@ namespace android { class BufferLayer : public Layer { public: - BufferLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, uint32_t w, - uint32_t h, uint32_t flags); - + explicit BufferLayer(const LayerCreationArgs& args); ~BufferLayer() override; // ----------------------------------------------------------------------- @@ -172,15 +172,15 @@ private: uint64_t getHeadFrameNumber() const; - uint32_t mCurrentScalingMode; + uint32_t mCurrentScalingMode{NATIVE_WINDOW_SCALING_MODE_FREEZE}; // main thread. - bool mBufferLatched; // TODO: Use mActiveBuffer? + bool mBufferLatched{false}; // TODO: Use mActiveBuffer? // The texture used to draw the layer in GLES composition mode mutable renderengine::Texture mTexture; - bool mRefreshPending; + bool mRefreshPending{false}; }; } // namespace android diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 521cdbf579..17706b52cb 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -21,24 +21,9 @@ namespace android { -BufferQueueLayer::BufferQueueLayer(SurfaceFlinger* flinger, const sp& client, - const String8& name, uint32_t w, uint32_t h, uint32_t flags) - : BufferLayer(flinger, client, name, w, h, flags), - mConsumer(nullptr), - mProducer(nullptr), - mFormat(PIXEL_FORMAT_NONE), - mPreviousFrameNumber(0), - mUpdateTexImageFailed(false), - mQueueItemLock(), - mQueueItemCondition(), - mQueueItems(), - mLastFrameNumberReceived(0), - mAutoRefresh(false), - mActiveBufferSlot(BufferQueue::INVALID_BUFFER_SLOT), - mQueuedFrames(0), - mSidebandStreamChanged(false) { - mCurrentState.requested_legacy = mCurrentState.active_legacy; -} +BufferQueueLayer::BufferQueueLayer(const LayerCreationArgs& args) : BufferLayer(args) {} + +BufferQueueLayer::~BufferQueueLayer() = default; // ----------------------------------------------------------------------- // Interface implementation for Layer diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 400f412d08..051b15d905 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -31,8 +31,8 @@ namespace android { */ class BufferQueueLayer : public BufferLayer, public BufferLayerConsumer::ContentsChangedListener { public: - BufferQueueLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, - uint32_t w, uint32_t h, uint32_t flags); + explicit BufferQueueLayer(const LayerCreationArgs&); + ~BufferQueueLayer() override; // ----------------------------------------------------------------------- // Interface implementation for Layer @@ -121,20 +121,20 @@ private: sp mConsumer; sp mProducer; - PixelFormat mFormat; + PixelFormat mFormat{PIXEL_FORMAT_NONE}; // Only accessed on the main thread. - uint64_t mPreviousFrameNumber; - bool mUpdateTexImageFailed; + uint64_t mPreviousFrameNumber{0}; + bool mUpdateTexImageFailed{false}; // Local copy of the queued contents of the incoming BufferQueue mutable Mutex mQueueItemLock; Condition mQueueItemCondition; Vector mQueueItems; - std::atomic mLastFrameNumberReceived; + std::atomic mLastFrameNumberReceived{0}; - bool mAutoRefresh; - int mActiveBufferSlot; + bool mAutoRefresh{false}; + int mActiveBufferSlot{BufferQueue::INVALID_BUFFER_SLOT}; // thread-safe std::atomic mQueuedFrames{0}; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index da9dcfbb05..9c10868473 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -26,18 +26,17 @@ namespace android { -static const std::array IDENTITY_MATRIX{1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1}; - -BufferStateLayer::BufferStateLayer(SurfaceFlinger* flinger, const sp& client, - const String8& name, uint32_t w, uint32_t h, uint32_t flags) - : BufferLayer(flinger, client, name, w, h, flags), - mSidebandStreamChanged(false), - mFrameNumber(0) { - mTransformMatrix = IDENTITY_MATRIX; -} +// clang-format off +const std::array BufferStateLayer::IDENTITY_MATRIX{ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 +}; +// clang-format on + +BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) : BufferLayer(args) {} +BufferStateLayer::~BufferStateLayer() = default; // ----------------------------------------------------------------------- // Interface implementation for Layer diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index ac3aad14b4..b662b96e84 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -29,8 +29,8 @@ namespace android { class BufferStateLayer : public BufferLayer { public: - BufferStateLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, - uint32_t w, uint32_t h, uint32_t flags); + explicit BufferStateLayer(const LayerCreationArgs&); + ~BufferStateLayer() override; // ----------------------------------------------------------------------- // Interface implementation for Layer @@ -125,13 +125,15 @@ private: private: void onFirstRef() override; + static const std::array IDENTITY_MATRIX; + std::unique_ptr mTextureImage; - std::array mTransformMatrix; + std::array mTransformMatrix{IDENTITY_MATRIX}; - std::atomic mSidebandStreamChanged; + std::atomic mSidebandStreamChanged{false}; - uint32_t mFrameNumber; + uint32_t mFrameNumber{0}; // TODO(marissaw): support sticky transform for LEGACY camera mode }; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 9bf75e83d2..b02c16c595 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -34,12 +34,9 @@ namespace android { // --------------------------------------------------------------------------- -ColorLayer::ColorLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, - uint32_t w, uint32_t h, uint32_t flags) - : Layer(flinger, client, name, w, h, flags) { - // drawing state & current state are identical - mDrawingState = mCurrentState; -} +ColorLayer::ColorLayer(const LayerCreationArgs& args) : Layer(args) {} + +ColorLayer::~ColorLayer() = default; void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */, bool useIdentityTransform) { @@ -72,9 +69,9 @@ void ColorLayer::setPerFrameData(const sp& display) { getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace; half4 color = getColor(); - getBE().compositionInfo.hwc.color = { static_cast(std::round(255.0f * color.r)), - static_cast(std::round(255.0f * color.g)), - static_cast(std::round(255.0f * color.b)), 255 }; + getBE().compositionInfo.hwc.color = {static_cast(std::round(255.0f * color.r)), + static_cast(std::round(255.0f * color.g)), + static_cast(std::round(255.0f * color.b)), 255}; // Clear out the transform, because it doesn't make sense absent a source buffer getBE().compositionInfo.hwc.transform = HWC2::Transform::None; diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index aa6b049aed..2c1035743e 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -25,9 +25,8 @@ namespace android { class ColorLayer : public Layer { public: - ColorLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, uint32_t w, - uint32_t h, uint32_t flags); - virtual ~ColorLayer() = default; + explicit ColorLayer(const LayerCreationArgs&); + ~ColorLayer() override; virtual const char* getTypeId() const { return "ColorLayer"; } virtual void onDraw(const RenderArea& renderArea, const Region& clip, diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index e9f3059d11..44e843e241 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -22,11 +22,9 @@ namespace android { -ContainerLayer::ContainerLayer(SurfaceFlinger* flinger, const sp& client, - const String8& name, uint32_t w, uint32_t h, uint32_t flags) - : Layer(flinger, client, name, w, h, flags) { - mDrawingState = mCurrentState; -} +ContainerLayer::ContainerLayer(const LayerCreationArgs& args) : Layer(args) {} + +ContainerLayer::~ContainerLayer() = default; void ContainerLayer::onDraw(const RenderArea&, const Region& /* clip */, bool) {} diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index 0b4a181d65..8eddc7f57b 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -25,9 +25,8 @@ namespace android { class ContainerLayer : public Layer { public: - ContainerLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, - uint32_t w, uint32_t h, uint32_t flags); - virtual ~ContainerLayer() = default; + explicit ContainerLayer(const LayerCreationArgs&); + ~ContainerLayer() override; const char* getTypeId() const override { return "ContainerLayer"; } void onDraw(const RenderArea& renderArea, const Region& clip, diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 19c84d0a85..f9bc1e7007 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -64,40 +64,22 @@ namespace android { std::atomic Layer::sSequence{1}; -Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& name, uint32_t w, - uint32_t h, uint32_t flags) - : contentDirty(false), - mFlinger(flinger), - mPremultipliedAlpha(true), - mName(name), - mTransactionFlags(0), - mPendingStateMutex(), - mPendingStates(), - mCurrentTransform(0), - mOverrideScalingMode(-1), - mCurrentFrameNumber(0), - mFrameLatencyNeeded(false), - mNeedsFiltering(false), - mProtectedByApp(false), - mClientRef(client), - mPotentialCursor(false), - mFreezeGeometryUpdates(false), - mCurrentChildren(LayerVector::StateSet::Current), - mDrawingChildren(LayerVector::StateSet::Drawing), - mBE{this, name.string()} { - +Layer::Layer(const LayerCreationArgs& args) + : mFlinger(args.flinger), + mName(args.name), + mClientRef(args.client), + mBE{this, args.name.string()} { mCurrentCrop.makeInvalid(); 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 (args.flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden; + if (args.flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque; + if (args.flags & ISurfaceComposerClient::eSecure) layerFlags |= layer_state_t::eLayerSecure; - mName = name; mTransactionName = String8("TX - ") + mName; - mCurrentState.active_legacy.w = w; - mCurrentState.active_legacy.h = h; + mCurrentState.active_legacy.w = args.w; + mCurrentState.active_legacy.h = args.h; mCurrentState.flags = layerFlags; mCurrentState.active_legacy.transform.set(0, 0); mCurrentState.crop_legacy.makeInvalid(); @@ -125,7 +107,7 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n mDrawingState = mCurrentState; CompositorTiming compositorTiming; - flinger->getCompositorTiming(&compositorTiming); + args.flinger->getCompositorTiming(&compositorTiming); mFrameEventHistory.initializeCompositorTiming(compositorTiming); mFrameTracker.setDisplayRefreshPeriod(compositorTiming.interval); } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 74f0a63be8..874b5513e3 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -72,6 +72,19 @@ class SurfaceInterceptor; // --------------------------------------------------------------------------- +struct LayerCreationArgs { + LayerCreationArgs(SurfaceFlinger* flinger, const sp& client, const String8& name, + uint32_t w, uint32_t h, uint32_t flags) + : flinger(flinger), client(client), name(name), w(w), h(h), flags(flags) {} + + SurfaceFlinger* flinger; + const sp& client; + const String8& name; + uint32_t w; + uint32_t h; + uint32_t flags; +}; + class Layer : public virtual RefBase { static std::atomic sSequence; @@ -79,7 +92,7 @@ public: friend class LayerBE; LayerBE& getBE() { return mBE; } LayerBE& getBE() const { return mBE; } - mutable bool contentDirty; + mutable bool contentDirty{false}; // regions below are in window-manager space Region visibleRegion; Region coveredRegion; @@ -170,8 +183,7 @@ public: sp sidebandStream; }; - Layer(SurfaceFlinger* flinger, const sp& client, const String8& name, uint32_t w, - uint32_t h, uint32_t flags); + explicit Layer(const LayerCreationArgs& args); virtual ~Layer(); void setPrimaryDisplayOnly() { mPrimaryDisplayOnly = true; } @@ -688,7 +700,7 @@ protected: // ----------------------------------------------------------------------- bool usingRelativeZ(LayerVector::StateSet stateSet); - bool mPremultipliedAlpha; + bool mPremultipliedAlpha{true}; String8 mName; String8 mTransactionName; // A cached version of "TX - " + mName for systraces @@ -719,18 +731,18 @@ protected: sp mActiveBuffer; ui::Dataspace mCurrentDataSpace = ui::Dataspace::UNKNOWN; Rect mCurrentCrop; - uint32_t mCurrentTransform; + uint32_t mCurrentTransform{0}; // We encode unset as -1. - int32_t mOverrideScalingMode; - std::atomic mCurrentFrameNumber; - bool mFrameLatencyNeeded; + int32_t mOverrideScalingMode{-1}; + std::atomic mCurrentFrameNumber{0}; + bool mFrameLatencyNeeded{false}; // Whether filtering is needed b/c of the drawingstate - bool mNeedsFiltering; + bool mNeedsFiltering{false}; - bool mPendingRemoval = false; + bool mPendingRemoval{false}; // page-flip thread (currently main thread) - bool mProtectedByApp; // application requires protected path to external sink + bool mProtectedByApp{false}; // application requires protected path to external sink // protected by mLock mutable Mutex mLock; @@ -738,14 +750,14 @@ protected: const wp mClientRef; // This layer can be a cursor on some displays. - bool mPotentialCursor; + bool mPotentialCursor{false}; - bool mFreezeGeometryUpdates; + bool mFreezeGeometryUpdates{false}; // Child list about to be committed/used for editing. - LayerVector mCurrentChildren; + LayerVector mCurrentChildren{LayerVector::StateSet::Current}; // Child list used for rendering. - LayerVector mDrawingChildren; + LayerVector mDrawingChildren{LayerVector::StateSet::Drawing}; wp mCurrentParent; wp mDrawingParent; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e2605b29f1..8dc22e971e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3873,7 +3873,8 @@ status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, const break; } - sp layer = new BufferQueueLayer(this, client, name, w, h, flags); + sp layer = + new BufferQueueLayer(LayerCreationArgs(this, client, name, w, h, flags)); status_t err = layer->setDefaultBufferProperties(w, h, format); if (err == NO_ERROR) { *handle = layer->getHandle(); @@ -3888,7 +3889,8 @@ status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, const status_t SurfaceFlinger::createBufferStateLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, sp* handle, sp* outLayer) { - sp layer = new BufferStateLayer(this, client, name, w, h, flags); + sp layer = + new BufferStateLayer(LayerCreationArgs(this, client, name, w, h, flags)); *handle = layer->getHandle(); *outLayer = layer; @@ -3899,7 +3901,7 @@ status_t SurfaceFlinger::createColorLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, sp* handle, sp* outLayer) { - *outLayer = new ColorLayer(this, client, name, w, h, flags); + *outLayer = new ColorLayer(LayerCreationArgs(this, client, name, w, h, flags)); *handle = (*outLayer)->getHandle(); return NO_ERROR; } @@ -3908,7 +3910,7 @@ status_t SurfaceFlinger::createContainerLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, sp* handle, sp* outLayer) { - *outLayer = new ContainerLayer(this, client, name, w, h, flags); + *outLayer = new ContainerLayer(LayerCreationArgs(this, client, name, w, h, flags)); *handle = (*outLayer)->getHandle(); return NO_ERROR; } @@ -5280,9 +5282,9 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, drawLayers(); } else { Rect bounds = getBounds(); - screenshotParentLayer = - new ContainerLayer(mFlinger, nullptr, String8("Screenshot Parent"), - bounds.getWidth(), bounds.getHeight(), 0); + screenshotParentLayer = new ContainerLayer( + LayerCreationArgs(mFlinger, nullptr, String8("Screenshot Parent"), + bounds.getWidth(), bounds.getHeight(), 0)); ReparentForDrawing reparent(mLayer, screenshotParentLayer); drawLayers(); diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 5aa6e27553..1299b05ee1 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -776,9 +776,10 @@ struct ColorLayerVariant : public BaseLayerVariant { static FlingerLayerType createLayer(CompositionTest* test) { FlingerLayerType layer = Base::template createLayerWithFactory(test, [test]() { - return new ColorLayer(test->mFlinger.mFlinger.get(), sp(), - String8("test-layer"), LayerProperties::WIDTH, - LayerProperties::HEIGHT, LayerProperties::LAYER_FLAGS); + return new ColorLayer(LayerCreationArgs(test->mFlinger.mFlinger.get(), sp(), + String8("test-layer"), LayerProperties::WIDTH, + LayerProperties::HEIGHT, + LayerProperties::LAYER_FLAGS)); }); return layer; } @@ -813,10 +814,11 @@ struct BufferLayerVariant : public BaseLayerVariant { FlingerLayerType layer = Base::template createLayerWithFactory(test, [test]() { - return new BufferQueueLayer(test->mFlinger.mFlinger.get(), sp(), - String8("test-layer"), LayerProperties::WIDTH, - LayerProperties::HEIGHT, - LayerProperties::LAYER_FLAGS); + return new BufferQueueLayer( + LayerCreationArgs(test->mFlinger.mFlinger.get(), sp(), + String8("test-layer"), LayerProperties::WIDTH, + LayerProperties::HEIGHT, + LayerProperties::LAYER_FLAGS)); }); LayerProperties::setupLayerState(test, layer); -- cgit v1.2.3-59-g8ed1b From d3788632cfc226386f7c7e30612ed2584b6ecb46 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Tue, 18 Sep 2018 16:01:31 -0700 Subject: [SurfaceFlinger] Implement per layer color transformation. Previously we introduced a new composer HAL API to set color transform for per layer and added the plumbing in SurfaceFlinger. This patch implements the functionality and alwasy mark those layers to fall back to GPU composition until composer 2.3 is implemented. BUG: 111562338 Test: Build, boot, flash, tested by setting a greyscale matrix on Settings Test: adb shell /data/nativetest/SurfaceFlinger_test/SurfaceFlinger_test Change-Id: If8d5ed52bf920d8cc962602196fb1b0b6e2955da --- libs/gui/LayerState.cpp | 9 ++++++ libs/gui/SurfaceComposerClient.cpp | 12 +++++++ libs/gui/include/gui/LayerState.h | 6 +++- libs/gui/include/gui/SurfaceComposerClient.h | 4 +++ services/surfaceflinger/BufferLayer.cpp | 1 + services/surfaceflinger/ColorLayer.cpp | 1 + services/surfaceflinger/Layer.cpp | 19 +++++++++++ services/surfaceflinger/Layer.h | 4 +++ services/surfaceflinger/LayerBE.cpp | 14 ++++++++ services/surfaceflinger/LayerBE.h | 1 + .../RenderEngine/gl/GLES20RenderEngine.cpp | 2 +- .../RenderEngine/gl/GLES20RenderEngine.h | 2 +- .../include/renderengine/RenderEngine.h | 5 +-- .../include/renderengine/private/Description.h | 2 ++ services/surfaceflinger/SurfaceFlinger.cpp | 37 ++++++++++++++++++---- services/surfaceflinger/SurfaceFlinger.h | 1 - services/surfaceflinger/tests/Transaction_test.cpp | 28 ++++++++++++++++ .../tests/unittests/CompositionTest.cpp | 2 +- .../unittests/mock/RenderEngine/MockRenderEngine.h | 2 +- 19 files changed, 138 insertions(+), 14 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 5a8d8dbc81..2b0a46181b 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -77,6 +77,9 @@ status_t layer_state_t::write(Parcel& output) const output.writeBool(false); } + memcpy(output.writeInplace(16 * sizeof(float)), + colorTransform.asArray(), 16 * sizeof(float)); + return NO_ERROR; } @@ -130,6 +133,8 @@ status_t layer_state_t::read(const Parcel& input) sidebandStream = NativeHandle::create(input.readNativeHandle(), true); } + colorTransform = mat4(static_cast(input.readInplace(16 * sizeof(float)))); + return NO_ERROR; } @@ -314,6 +319,10 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eSidebandStreamChanged; sidebandStream = other.sidebandStream; } + if (other.what & eColorTransformChanged) { + what |= eColorTransformChanged; + colorTransform = other.colorTransform; + } if ((other.what & what) != other.what) { ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? " diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 09ea0f601a..1ac96094cc 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -602,6 +602,18 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::destroyS return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColorTransform( + const sp& sc, const mat3& matrix, const vec3& translation) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eColorTransformChanged; + s->colorTransform = mat4(matrix, translation); + return *this; +} + // --------------------------------------------------------------------------- DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp& token) { diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 9a9f633ed7..e06e2b14b9 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -72,6 +73,7 @@ struct layer_state_t { eSurfaceDamageRegionChanged = 0x02000000, eApiChanged = 0x04000000, eSidebandStreamChanged = 0x08000000, + eColorTransformChanged = 0x10000000, }; layer_state_t() @@ -94,7 +96,8 @@ struct layer_state_t { crop(Rect::INVALID_RECT), dataspace(ui::Dataspace::UNKNOWN), surfaceDamageRegion(), - api(-1) { + api(-1), + colorTransform(mat4()) { matrix.dsdx = matrix.dtdy = 1.0f; matrix.dsdy = matrix.dtdx = 0.0f; hdrMetadata.validTypes = 0; @@ -150,6 +153,7 @@ struct layer_state_t { Region surfaceDamageRegion; int32_t api; sp sidebandStream; + mat4 colorTransform; }; struct ComposerState { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 314b1182b4..69a759fb4e 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -269,6 +269,10 @@ public: Transaction& destroySurface(const sp& sc); + // Set a color transform matrix on the given layer on the built-in display. + Transaction& setColorTransform(const sp& sc, const mat3& matrix, + const vec3& translation); + status_t setDisplaySurface(const sp& token, const sp& bufferProducer); diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 642ed2fefc..1a73ff0391 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -258,6 +258,7 @@ void BufferLayer::setPerFrameData(const sp& display) { getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace; getBE().compositionInfo.hwc.hdrMetadata = getDrawingHdrMetadata(); getBE().compositionInfo.hwc.supportedPerFrameMetadata = display->getSupportedPerFrameMetadata(); + getBE().compositionInfo.hwc.colorTransform = getColorTransform(); setHwcLayerBuffer(display); } diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index b02c16c595..3a554c9e44 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -75,6 +75,7 @@ void ColorLayer::setPerFrameData(const sp& display) { // Clear out the transform, because it doesn't make sense absent a source buffer getBE().compositionInfo.hwc.transform = HWC2::Transform::None; + getBE().compositionInfo.hwc.colorTransform = getColorTransform(); } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f9bc1e7007..8afd3b3df4 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1546,6 +1546,25 @@ bool Layer::detachChildren() { return true; } +bool Layer::setColorTransform(const mat4& matrix) { + if (mCurrentState.colorTransform == matrix) { + return false; + } + ++mCurrentState.sequence; + mCurrentState.colorTransform = matrix; + setTransactionFlags(eTransactionNeeded); + return true; +} + +const mat4& Layer::getColorTransform() const { + return getDrawingState().colorTransform; +} + +bool Layer::hasColorTransform() const { + static const mat4 identityMatrix = mat4(); + return getDrawingState().colorTransform != identityMatrix; +} + bool Layer::isLegacyDataSpace() const { // return true when no higher bits are set return !(mCurrentDataSpace & (ui::Dataspace::STANDARD_MASK | diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 874b5513e3..4890fa603a 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -181,6 +181,7 @@ public: int32_t api; sp sidebandStream; + mat4 colorTransform; }; explicit Layer(const LayerCreationArgs& args); @@ -255,6 +256,9 @@ public: virtual void setChildrenDrawingParent(const sp& layer); virtual bool reparent(const sp& newParentHandle); virtual bool detachChildren(); + virtual bool setColorTransform(const mat4& matrix); + virtual const mat4& getColorTransform() const; + virtual bool hasColorTransform() const; // Used only to set BufferStateLayer state virtual bool setTransform(uint32_t /*transform*/) { return false; }; diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp index ef017aa9d5..c9b793377a 100644 --- a/services/surfaceflinger/LayerBE.cpp +++ b/services/surfaceflinger/LayerBE.cpp @@ -112,6 +112,20 @@ void CompositionInfo::dumpHwc(std::string& result, const char* tag) const { hwc.surfaceDamage.dump(regionString, "surfaceDamage"); result += regionString.string(); } + + result += base::StringPrintf("\tcolor transform matrix:\n" + "\t\t[%f, %f, %f, %f,\n" + "\t\t %f, %f, %f, %f,\n" + "\t\t %f, %f, %f, %f,\n" + "\t\t %f, %f, %f, %f]\n", + hwc.colorTransform[0][0], hwc.colorTransform[1][0], + hwc.colorTransform[2][0], hwc.colorTransform[3][0], + hwc.colorTransform[0][1], hwc.colorTransform[1][1], + hwc.colorTransform[2][1], hwc.colorTransform[3][1], + hwc.colorTransform[0][2], hwc.colorTransform[1][2], + hwc.colorTransform[2][2], hwc.colorTransform[3][2], + hwc.colorTransform[0][3], hwc.colorTransform[1][3], + hwc.colorTransform[2][3], hwc.colorTransform[3][3]); } void CompositionInfo::dumpRe(std::string& result, const char* tag) const { diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 2722b01ea2..d63d16f59e 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -60,6 +60,7 @@ struct CompositionInfo { bool clearClientTarget = false; bool supportedPerFrameMetadata = false; HdrMetadata hdrMetadata; + mat4 colorTransform; } hwc; struct { bool blackoutLayer = false; diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp index 813c9e60ad..1b0a539f24 100644 --- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp @@ -743,7 +743,7 @@ void GLES20RenderEngine::setupLayerBlackedOut() { mState.textureEnabled = true; } -void GLES20RenderEngine::setupColorTransform(const mat4& colorTransform) { +void GLES20RenderEngine::setColorTransform(const mat4& colorTransform) { mState.colorMatrix = colorTransform; } diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h index fa0141046f..4f03a904a9 100644 --- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h @@ -86,7 +86,7 @@ protected: void setupLayerTexturing(const Texture& texture) override; void setupLayerBlackedOut() override; void setupFillWithColor(float r, float g, float b, float a) override; - void setupColorTransform(const mat4& colorTransform) override; + void setColorTransform(const mat4& colorTransform) override; void disableTexturing() override; void disableBlending() override; diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h index 05668f8ce4..122271f9d6 100644 --- a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h @@ -115,7 +115,9 @@ public: virtual void setupLayerTexturing(const Texture& texture) = 0; virtual void setupLayerBlackedOut() = 0; virtual void setupFillWithColor(float r, float g, float b, float a) = 0; - virtual void setupColorTransform(const mat4& /* colorTransform */) = 0; + + // Set a color transform matrix that is applied in linear space right before OETF. + virtual void setColorTransform(const mat4& /* colorTransform */) = 0; virtual void disableTexturing() = 0; virtual void disableBlending() = 0; @@ -163,7 +165,6 @@ public: bool useNativeFenceSync() const override; bool useWaitSync() const override; - void setupColorTransform(const mat4& /* colorTransform */) override {} protected: RenderEngine(uint32_t featureFlags); diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h b/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h index efab8ffb70..911bb7aacd 100644 --- a/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h +++ b/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h @@ -68,6 +68,8 @@ struct Description { // projection matrix mat4 projectionMatrix; + + // The color matrix will be applied in linear space right before OETF. mat4 colorMatrix; mat4 inputTransformMatrix; mat4 outputTransformMatrix; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9410cdb64c..c37b3b19b8 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1604,6 +1604,11 @@ void SurfaceFlinger::calculateWorkingSet() { layer->forceClientComposition(displayId); } + // TODO(b/111562338) remove when composer 2.3 is shipped. + if (layer->hasColorTransform()) { + layer->forceClientComposition(displayId); + } + if (layer->getForceClientComposition(displayId)) { ALOGV("[%s] Requesting Client composition", layer->getName().string()); layer->setCompositionType(displayId, HWC2::Composition::Client); @@ -2141,6 +2146,8 @@ void SurfaceFlinger::configureHwcCommonData(const CompositionInfo& compositionIn ALOGE_IF(error != HWC2::Error::None, "[SF] Failed to set surface damage: %s (%d)", to_string(error).c_str(), static_cast(error)); + + error = (compositionInfo.hwc.hwcLayer)->setColorTransform(compositionInfo.hwc.colorTransform); } void SurfaceFlinger::configureDeviceComposition(const CompositionInfo& compositionInfo) const @@ -3091,6 +3098,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& display) { const bool hasClientComposition = getBE().mHwc->hasClientComposition(displayId); ATRACE_INT("hasClientComposition", hasClientComposition); + mat4 colorMatrix; bool applyColorMatrix = false; bool needsEnhancedColorMatrix = false; @@ -3109,7 +3117,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& display) { const bool skipClientColorTransform = getBE().mHwc->hasCapability( HWC2::Capability::SkipClientColorTransform); - mat4 colorMatrix; + // Compute the global color transform matrix. applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform; if (applyColorMatrix) { colorMatrix = mDrawingState.colorMatrix; @@ -3125,8 +3133,6 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& display) { colorMatrix *= mEnhancedSaturationMatrix; } - getRenderEngine().setupColorTransform(colorMatrix); - if (!display->makeCurrent()) { ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s", display->getDisplayName().c_str()); @@ -3205,6 +3211,19 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& display) { break; } case HWC2::Composition::Client: { + if (layer->hasColorTransform()) { + mat4 tmpMatrix; + if (applyColorMatrix) { + tmpMatrix = mDrawingState.colorMatrix; + } + tmpMatrix *= layer->getColorTransform(); + if (needsEnhancedColorMatrix) { + tmpMatrix *= mEnhancedSaturationMatrix; + } + getRenderEngine().setColorTransform(tmpMatrix); + } else { + getRenderEngine().setColorTransform(colorMatrix); + } layer->draw(renderArea, clip); break; } @@ -3217,9 +3236,8 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& display) { firstLayer = false; } - if (applyColorMatrix || needsEnhancedColorMatrix) { - getRenderEngine().setupColorTransform(mat4()); - } + // Clear color transform matrix at the end of the frame. + getRenderEngine().setColorTransform(mat4()); // disable scissor at the end of the frame getBE().mRenderEngine->disableScissor(); @@ -3596,6 +3614,11 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState if (layer->setColor(s.color)) flags |= eTraversalNeeded; } + if (what & layer_state_t::eColorTransformChanged) { + if (layer->setColorTransform(s.colorTransform)) { + flags |= eTraversalNeeded; + } + } if (what & layer_state_t::eMatrixChanged) { // TODO: b/109894387 // @@ -5441,7 +5464,9 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, engine.clearWithColor(0, 0, 0, alpha); traverseLayers([&](Layer* layer) { + engine.setColorTransform(layer->getColorTransform()); layer->draw(renderArea, useIdentityTransform); + engine.setColorTransform(mat4()); }); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b77bf48361..3f3086b252 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -454,7 +454,6 @@ private: status_t getCompositionPreference(ui::Dataspace* outDataSpace, ui::PixelFormat* outPixelFormat) const override; - /* ------------------------------------------------------------------------ * DeathRecipient interface */ diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 3af98e5c9b..3166a8c752 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -2064,6 +2064,34 @@ TEST_F(LayerTransactionTest, SetSidebandStreamNull_BufferState) { Transaction().setSidebandStream(layer, nullptr).apply(); } +TEST_F(LayerTransactionTest, SetColorTransformBasic) { + sp colorLayer; + ASSERT_NO_FATAL_FAILURE( + colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor)); + + Transaction().setLayer(colorLayer, mLayerZBase + 1).apply(); + { + SCOPED_TRACE("default color"); + screenshot()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); + } + + const half3 color(50.0f / 255.0f, 100.0f / 255.0f, 150.0f / 255.0f); + const Color expected = {90, 90, 90, 255}; + // this is handwavy, but the precison loss scaled by 255 (8-bit per + // channel) should be less than one + const uint8_t tolerance = 1; + mat3 matrix; + matrix[0][0] = 0.3; matrix[1][0] = 0.59; matrix[2][0] = 0.11; + matrix[0][1] = 0.3; matrix[1][1] = 0.59; matrix[2][1] = 0.11; + matrix[0][2] = 0.3; matrix[1][2] = 0.59; matrix[2][2] = 0.11; + Transaction().setColor(colorLayer, color) + .setColorTransform(colorLayer, matrix, vec3()).apply(); + { + SCOPED_TRACE("new color"); + screenshot()->expectColor(Rect(0, 0, 32, 32), expected, tolerance); + } +} + class LayerUpdateTest : public LayerTransactionTest { protected: virtual void SetUp() { diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 52e64d82ac..3caf1f6823 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -325,7 +325,7 @@ struct BaseDisplayVariant { EXPECT_CALL(*test->mRenderEngine, setOutputDataSpace(ui::Dataspace::UNKNOWN)).Times(1); EXPECT_CALL(*test->mRenderEngine, setDisplayMaxLuminance(DEFAULT_DISPLAY_MAX_LUMINANCE)) .Times(1); - EXPECT_CALL(*test->mRenderEngine, setupColorTransform(_)).Times(2); + EXPECT_CALL(*test->mRenderEngine, setColorTransform(_)).Times(2); // These expectations retire on saturation as the code path these // expectations are for appears to make an extra call to them. // TODO: Investigate this extra call diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h index c29452c0d2..6813cdaa7b 100644 --- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h +++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h @@ -62,7 +62,7 @@ public: MOCK_METHOD1(setupLayerTexturing, void(const Texture&)); MOCK_METHOD0(setupLayerBlackedOut, void()); MOCK_METHOD4(setupFillWithColor, void(float, float, float, float)); - MOCK_METHOD1(setupColorTransform, void(const mat4&)); + MOCK_METHOD1(setColorTransform, void(const mat4&)); MOCK_METHOD1(setSaturationMatrix, void(const mat4&)); MOCK_METHOD0(disableTexturing, void()); MOCK_METHOD0(disableBlending, void()); -- cgit v1.2.3-59-g8ed1b From 4340607f5f5c277eb031fdd1424fc8a1a69924e2 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Wed, 19 Sep 2018 13:22:47 -0700 Subject: SurfaceFlinger: Allows Surfaces to outlive their parents. Currently the only strong reference to a Layer is held by their parent or the containing layer stack. This has a few undesirable implications. Firstly, it means that we can not create a SurfaceControl with a null parent. For example, a media decoding library may wish to offer an unparented SurfaceControl representing the decoding Surface, and allow the consumer to parent it between various SurfaceControls as they wish. Secondly it requires lifetime coordination between various levels of the hierarchy, when adding a child you have to be careful to observe the lifetime of the parent because your BufferQueue may become suddenly abandoned at any point. In this change we switch to a reference counted model, such that the Layer remains valid as long as there is a handle to it. We also end the behavior of passing on BufferQueue abandon to children. Layers are only abandoned/disposed when an explicit call to remove is made, or the last reference is dropped. Bug: 62536731 Bug: 111373437 Bug: 111297488 Test: Transaction_test.cpp Change-Id: I04cbc2368a1049b8ebd8913673ed4bfe05a26280 --- services/surfaceflinger/Layer.cpp | 19 ++++----- services/surfaceflinger/Layer.h | 8 ++-- services/surfaceflinger/SurfaceFlinger.cpp | 49 +++------------------- services/surfaceflinger/SurfaceFlinger.h | 5 --- services/surfaceflinger/tests/Transaction_test.cpp | 31 ++++++++++++++ 5 files changed, 49 insertions(+), 63 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f9bc1e7007..63a010d725 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -118,12 +118,6 @@ Layer::~Layer() { c->detachLayer(this); } - for (auto& point : mRemoteSyncPoints) { - point->setTransactionApplied(); - } - for (auto& point : mLocalSyncPoints) { - point->setFrameAvailable(); - } mFrameTracker.logAndResetStats(mName); } @@ -141,8 +135,6 @@ void Layer::onLayerDisplayed(const sp& /*releaseFence*/) {} void Layer::onRemovedFromCurrentState() { // the layer is removed from SF mCurrentState to mLayersPendingRemoval - mPendingRemoval = true; - if (mCurrentState.zOrderRelativeOf != nullptr) { sp strongRelative = mCurrentState.zOrderRelativeOf.promote(); if (strongRelative != nullptr) { @@ -151,7 +143,7 @@ void Layer::onRemovedFromCurrentState() { } mCurrentState.zOrderRelativeOf = nullptr; } - + for (const auto& child : mCurrentChildren) { child->onRemovedFromCurrentState(); } @@ -163,8 +155,13 @@ void Layer::onRemoved() { destroyAllHwcLayers(); - for (const auto& child : mCurrentChildren) { - child->onRemoved(); + mRemoved = true; + + for (auto& point : mRemoteSyncPoints) { + point->setTransactionApplied(); + } + for (auto& point : mLocalSyncPoints) { + point->setFrameAvailable(); } } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 874b5513e3..3e6eba4ff7 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -341,7 +341,7 @@ public: virtual bool isCreatedFromMainThread() const { return false; } - bool isPendingRemoval() const { return mPendingRemoval; } + bool isRemoved() const { return mRemoved; } void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing); @@ -589,12 +589,12 @@ protected: */ class LayerCleaner { sp mFlinger; - wp mLayer; + sp mLayer; protected: ~LayerCleaner() { // destroy client resources - mFlinger->onLayerDestroyed(mLayer); + mFlinger->removeLayer(mLayer, true); } public: @@ -739,7 +739,7 @@ protected: // Whether filtering is needed b/c of the drawingstate bool mNeedsFiltering{false}; - bool mPendingRemoval{false}; + bool mRemoved{false}; // page-flip thread (currently main thread) bool mProtectedByApp{false}; // application requires protected path to external sink diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9410cdb64c..7ccf8bc00d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2833,6 +2833,7 @@ void SurfaceFlinger::commitTransaction() recordBufferingStats(l->getName().string(), l->getOccupancyHistory(true)); l->onRemoved(); + mNumLayers -= 1; } mLayersPendingRemoval.clear(); } @@ -3248,7 +3249,7 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, if (parent == nullptr) { mCurrentState.layersSortedByZ.add(lbc); } else { - if (parent->isPendingRemoval()) { + if (parent->isRemoved()) { ALOGE("addClientLayer called with a removed parent"); return NAME_NOT_FOUND; } @@ -3280,7 +3281,7 @@ status_t SurfaceFlinger::removeLayer(const sp& layer, bool topLevelOnly) status_t SurfaceFlinger::removeLayerLocked(const Mutex&, const sp& layer, bool topLevelOnly) { - if (layer->isPendingRemoval()) { + if (layer->isRemoved()) { return NO_ERROR; } @@ -3290,39 +3291,14 @@ status_t SurfaceFlinger::removeLayerLocked(const Mutex&, const sp& layer, if (topLevelOnly) { return NO_ERROR; } - - sp ancestor = p; - while (ancestor->getParent() != nullptr) { - ancestor = ancestor->getParent(); - } - if (mCurrentState.layersSortedByZ.indexOf(ancestor) < 0) { - ALOGE("removeLayer called with a layer whose parent has been removed"); - return NAME_NOT_FOUND; - } - index = p->removeChild(layer); } else { index = mCurrentState.layersSortedByZ.remove(layer); } - // As a matter of normal operation, the LayerCleaner will produce a second - // attempt to remove the surface. The Layer will be kept alive in mDrawingState - // so we will succeed in promoting it, but it's already been removed - // from mCurrentState. As long as we can find it in mDrawingState we have no problem - // otherwise something has gone wrong and we are leaking the layer. - if (index < 0 && mDrawingState.layersSortedByZ.indexOf(layer) < 0) { - ALOGE("Failed to find layer (%s) in layer parent (%s).", - layer->getName().string(), - (p != nullptr) ? p->getName().string() : "no-parent"); - return BAD_VALUE; - } else if (index < 0) { - return NO_ERROR; - } - layer->onRemovedFromCurrentState(); mLayersPendingRemoval.add(layer); mLayersRemoved = true; - mNumLayers -= 1 + layer->getChildrenCount(); setTransactionFlags(eTransactionNeeded); return NO_ERROR; } @@ -3525,7 +3501,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState return 0; } - if (layer->isPendingRemoval()) { + if (layer->isRemoved()) { ALOGW("Attempting to set client state on removed layer: %s", layer->getName().string()); return 0; } @@ -3728,7 +3704,7 @@ void SurfaceFlinger::setDestroyStateLocked(const ComposerState& composerState) { return; } - if (layer->isPendingRemoval()) { + if (layer->isRemoved()) { ALOGW("Attempting to destroy on removed layer: %s", layer->getName().string()); return; } @@ -3905,19 +3881,6 @@ status_t SurfaceFlinger::onLayerRemoved(const sp& client, const sp& layer) -{ - // called by ~LayerCleaner() when all references to the IBinder (handle) - // are gone - sp l = layer.promote(); - if (l == nullptr) { - // The layer has already been removed, carry on - return NO_ERROR; - } - // If we have a parent, then we can continue to live as long as it does. - return removeLayer(l, true); -} - // --------------------------------------------------------------------------- void SurfaceFlinger::onInitializeDisplays() { @@ -5291,7 +5254,7 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, auto layerHandle = reinterpret_cast(layerHandleBinder.get()); auto parent = layerHandle->owner.promote(); - if (parent == nullptr || parent->isPendingRemoval()) { + if (parent == nullptr || parent->isRemoved()) { ALOGE("captureLayers called with a removed parent"); return NAME_NOT_FOUND; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b77bf48361..1bf1c5a358 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -559,11 +559,6 @@ private: // ISurfaceComposerClient::destroySurface() status_t onLayerRemoved(const sp& client, const sp& handle); - // called when all clients have released all their references to - // this layer meaning it is entirely safe to destroy all - // resources associated to this layer. - status_t onLayerDestroyed(const wp& layer); - // remove a layer from SurfaceFlinger immediately status_t removeLayer(const sp& layer, bool topLevelOnly = false); status_t removeLayerLocked(const Mutex&, const sp& layer, bool topLevelOnly = false); diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 3af98e5c9b..5e3733257e 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -2554,6 +2554,37 @@ TEST_F(ChildLayerTest, DetachChildrenSameClient) { } } +TEST_F(ChildLayerTest, ChildrenSurviveParentDestruction) { + sp mGrandChild = + mClient->createSurface(String8("Grand Child"), 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mChild.get()); + fillSurfaceRGBA8(mGrandChild, 111, 111, 111); + + { + SCOPED_TRACE("Grandchild visible"); + ScreenCapture::captureScreen(&mCapture); + mCapture->checkPixel(64, 64, 111, 111, 111); + } + + mChild->clear(); + + { + SCOPED_TRACE("After destroying child"); + ScreenCapture::captureScreen(&mCapture); + mCapture->expectFGColor(64, 64); + } + + asTransaction([&](Transaction& t) { + t.reparent(mGrandChild, mFGSurfaceControl->getHandle()); + }); + + { + SCOPED_TRACE("After reparenting grandchild"); + ScreenCapture::captureScreen(&mCapture); + mCapture->checkPixel(64, 64, 111, 111, 111); + } +} + TEST_F(ChildLayerTest, DetachChildrenDifferentClient) { sp mNewComposerClient = new SurfaceComposerClient; sp mChildNewClient = -- cgit v1.2.3-59-g8ed1b From 4bba3709d2848cc352c517e375ad2c295bc20ee8 Mon Sep 17 00:00:00 2001 From: Rob Carr Date: Mon, 8 Oct 2018 21:53:30 +0000 Subject: Revert "SurfaceFlinger: Allows Surfaces to outlive their parents." This reverts commit 4340607f5f5c277eb031fdd1424fc8a1a69924e2. Reason for revert: Causes bug 117401269 Change-Id: I10973c9dd734499e09c18f48c06f1b1a6a1f8da0 --- services/surfaceflinger/Layer.cpp | 19 +++++---- services/surfaceflinger/Layer.h | 8 ++-- services/surfaceflinger/SurfaceFlinger.cpp | 49 +++++++++++++++++++--- services/surfaceflinger/SurfaceFlinger.h | 5 +++ services/surfaceflinger/tests/Transaction_test.cpp | 31 -------------- 5 files changed, 63 insertions(+), 49 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 63a010d725..f9bc1e7007 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -118,6 +118,12 @@ Layer::~Layer() { c->detachLayer(this); } + for (auto& point : mRemoteSyncPoints) { + point->setTransactionApplied(); + } + for (auto& point : mLocalSyncPoints) { + point->setFrameAvailable(); + } mFrameTracker.logAndResetStats(mName); } @@ -135,6 +141,8 @@ void Layer::onLayerDisplayed(const sp& /*releaseFence*/) {} void Layer::onRemovedFromCurrentState() { // the layer is removed from SF mCurrentState to mLayersPendingRemoval + mPendingRemoval = true; + if (mCurrentState.zOrderRelativeOf != nullptr) { sp strongRelative = mCurrentState.zOrderRelativeOf.promote(); if (strongRelative != nullptr) { @@ -143,7 +151,7 @@ void Layer::onRemovedFromCurrentState() { } mCurrentState.zOrderRelativeOf = nullptr; } - + for (const auto& child : mCurrentChildren) { child->onRemovedFromCurrentState(); } @@ -155,13 +163,8 @@ void Layer::onRemoved() { destroyAllHwcLayers(); - mRemoved = true; - - for (auto& point : mRemoteSyncPoints) { - point->setTransactionApplied(); - } - for (auto& point : mLocalSyncPoints) { - point->setFrameAvailable(); + for (const auto& child : mCurrentChildren) { + child->onRemoved(); } } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 3e6eba4ff7..874b5513e3 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -341,7 +341,7 @@ public: virtual bool isCreatedFromMainThread() const { return false; } - bool isRemoved() const { return mRemoved; } + bool isPendingRemoval() const { return mPendingRemoval; } void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing); @@ -589,12 +589,12 @@ protected: */ class LayerCleaner { sp mFlinger; - sp mLayer; + wp mLayer; protected: ~LayerCleaner() { // destroy client resources - mFlinger->removeLayer(mLayer, true); + mFlinger->onLayerDestroyed(mLayer); } public: @@ -739,7 +739,7 @@ protected: // Whether filtering is needed b/c of the drawingstate bool mNeedsFiltering{false}; - bool mRemoved{false}; + bool mPendingRemoval{false}; // page-flip thread (currently main thread) bool mProtectedByApp{false}; // application requires protected path to external sink diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7ccf8bc00d..9410cdb64c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2833,7 +2833,6 @@ void SurfaceFlinger::commitTransaction() recordBufferingStats(l->getName().string(), l->getOccupancyHistory(true)); l->onRemoved(); - mNumLayers -= 1; } mLayersPendingRemoval.clear(); } @@ -3249,7 +3248,7 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, if (parent == nullptr) { mCurrentState.layersSortedByZ.add(lbc); } else { - if (parent->isRemoved()) { + if (parent->isPendingRemoval()) { ALOGE("addClientLayer called with a removed parent"); return NAME_NOT_FOUND; } @@ -3281,7 +3280,7 @@ status_t SurfaceFlinger::removeLayer(const sp& layer, bool topLevelOnly) status_t SurfaceFlinger::removeLayerLocked(const Mutex&, const sp& layer, bool topLevelOnly) { - if (layer->isRemoved()) { + if (layer->isPendingRemoval()) { return NO_ERROR; } @@ -3291,14 +3290,39 @@ status_t SurfaceFlinger::removeLayerLocked(const Mutex&, const sp& layer, if (topLevelOnly) { return NO_ERROR; } + + sp ancestor = p; + while (ancestor->getParent() != nullptr) { + ancestor = ancestor->getParent(); + } + if (mCurrentState.layersSortedByZ.indexOf(ancestor) < 0) { + ALOGE("removeLayer called with a layer whose parent has been removed"); + return NAME_NOT_FOUND; + } + index = p->removeChild(layer); } else { index = mCurrentState.layersSortedByZ.remove(layer); } + // As a matter of normal operation, the LayerCleaner will produce a second + // attempt to remove the surface. The Layer will be kept alive in mDrawingState + // so we will succeed in promoting it, but it's already been removed + // from mCurrentState. As long as we can find it in mDrawingState we have no problem + // otherwise something has gone wrong and we are leaking the layer. + if (index < 0 && mDrawingState.layersSortedByZ.indexOf(layer) < 0) { + ALOGE("Failed to find layer (%s) in layer parent (%s).", + layer->getName().string(), + (p != nullptr) ? p->getName().string() : "no-parent"); + return BAD_VALUE; + } else if (index < 0) { + return NO_ERROR; + } + layer->onRemovedFromCurrentState(); mLayersPendingRemoval.add(layer); mLayersRemoved = true; + mNumLayers -= 1 + layer->getChildrenCount(); setTransactionFlags(eTransactionNeeded); return NO_ERROR; } @@ -3501,7 +3525,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState return 0; } - if (layer->isRemoved()) { + if (layer->isPendingRemoval()) { ALOGW("Attempting to set client state on removed layer: %s", layer->getName().string()); return 0; } @@ -3704,7 +3728,7 @@ void SurfaceFlinger::setDestroyStateLocked(const ComposerState& composerState) { return; } - if (layer->isRemoved()) { + if (layer->isPendingRemoval()) { ALOGW("Attempting to destroy on removed layer: %s", layer->getName().string()); return; } @@ -3881,6 +3905,19 @@ status_t SurfaceFlinger::onLayerRemoved(const sp& client, const sp& layer) +{ + // called by ~LayerCleaner() when all references to the IBinder (handle) + // are gone + sp l = layer.promote(); + if (l == nullptr) { + // The layer has already been removed, carry on + return NO_ERROR; + } + // If we have a parent, then we can continue to live as long as it does. + return removeLayer(l, true); +} + // --------------------------------------------------------------------------- void SurfaceFlinger::onInitializeDisplays() { @@ -5254,7 +5291,7 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, auto layerHandle = reinterpret_cast(layerHandleBinder.get()); auto parent = layerHandle->owner.promote(); - if (parent == nullptr || parent->isRemoved()) { + if (parent == nullptr || parent->isPendingRemoval()) { ALOGE("captureLayers called with a removed parent"); return NAME_NOT_FOUND; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 1bf1c5a358..b77bf48361 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -559,6 +559,11 @@ private: // ISurfaceComposerClient::destroySurface() status_t onLayerRemoved(const sp& client, const sp& handle); + // called when all clients have released all their references to + // this layer meaning it is entirely safe to destroy all + // resources associated to this layer. + status_t onLayerDestroyed(const wp& layer); + // remove a layer from SurfaceFlinger immediately status_t removeLayer(const sp& layer, bool topLevelOnly = false); status_t removeLayerLocked(const Mutex&, const sp& layer, bool topLevelOnly = false); diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 5e3733257e..3af98e5c9b 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -2554,37 +2554,6 @@ TEST_F(ChildLayerTest, DetachChildrenSameClient) { } } -TEST_F(ChildLayerTest, ChildrenSurviveParentDestruction) { - sp mGrandChild = - mClient->createSurface(String8("Grand Child"), 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mChild.get()); - fillSurfaceRGBA8(mGrandChild, 111, 111, 111); - - { - SCOPED_TRACE("Grandchild visible"); - ScreenCapture::captureScreen(&mCapture); - mCapture->checkPixel(64, 64, 111, 111, 111); - } - - mChild->clear(); - - { - SCOPED_TRACE("After destroying child"); - ScreenCapture::captureScreen(&mCapture); - mCapture->expectFGColor(64, 64); - } - - asTransaction([&](Transaction& t) { - t.reparent(mGrandChild, mFGSurfaceControl->getHandle()); - }); - - { - SCOPED_TRACE("After reparenting grandchild"); - ScreenCapture::captureScreen(&mCapture); - mCapture->checkPixel(64, 64, 111, 111, 111); - } -} - TEST_F(ChildLayerTest, DetachChildrenDifferentClient) { sp mNewComposerClient = new SurfaceComposerClient; sp mChildNewClient = -- cgit v1.2.3-59-g8ed1b From 747321cc8dd2810b53992f8b35d548d600ddc9b6 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Mon, 1 Oct 2018 10:03:11 -0700 Subject: [SurfaceFlinger] Avoid comparing to identity matrix. hasColorTransform is called every time on every layer that needs to be client composited. This patch adds a boolean for that check and move that check to when color transform matrix is set. BUG: 111562338 Test: Build, flash and boot. Change-Id: Icbd17458dc194f10f744ee7cc72c3462ae239a28 --- services/surfaceflinger/Layer.cpp | 8 ++++++-- services/surfaceflinger/Layer.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 8afd3b3df4..7e6b5d3d58 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -102,6 +102,7 @@ Layer::Layer(const LayerCreationArgs& args) mCurrentState.hdrMetadata.validTypes = 0; mCurrentState.surfaceDamageRegion.clear(); mCurrentState.api = -1; + mCurrentState.hasColorTransform = false; // drawing state & current state are identical mDrawingState = mCurrentState; @@ -1547,11 +1548,15 @@ bool Layer::detachChildren() { } bool Layer::setColorTransform(const mat4& matrix) { + static const mat4 identityMatrix = mat4(); + if (mCurrentState.colorTransform == matrix) { return false; } ++mCurrentState.sequence; mCurrentState.colorTransform = matrix; + mCurrentState.hasColorTransform = matrix != identityMatrix; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } @@ -1561,8 +1566,7 @@ const mat4& Layer::getColorTransform() const { } bool Layer::hasColorTransform() const { - static const mat4 identityMatrix = mat4(); - return getDrawingState().colorTransform != identityMatrix; + return getDrawingState().hasColorTransform; } bool Layer::isLegacyDataSpace() const { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index e2d1178892..5d05f0530b 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -182,6 +182,7 @@ public: sp sidebandStream; mat4 colorTransform; + bool hasColorTransform; }; explicit Layer(const LayerCreationArgs& args); -- cgit v1.2.3-59-g8ed1b From 1509411dd90a56b2c4cc7a729ff31842f4d7ffa1 Mon Sep 17 00:00:00 2001 From: David Sodman Date: Thu, 11 Oct 2018 09:39:37 -0700 Subject: Revert "SF: Use CompositionInfo to program HWComposer" This reverts commit 10a41ffcf1465935c87266d18b279a228ab905d2. Bug: 117282234 Test: None Change-Id: Id33609ab4f52a9e79568ad0777b6f79439b19588 --- services/surfaceflinger/BufferLayer.cpp | 62 ++++++-- services/surfaceflinger/BufferQueueLayer.cpp | 16 +- services/surfaceflinger/ColorLayer.cpp | 52 +++++- services/surfaceflinger/Layer.cpp | 79 ++++++--- services/surfaceflinger/LayerBE.cpp | 4 +- services/surfaceflinger/LayerBE.h | 3 +- services/surfaceflinger/SurfaceFlinger.cpp | 177 +-------------------- services/surfaceflinger/SurfaceFlinger.h | 6 - .../tests/unittests/CompositionTest.cpp | 3 +- 9 files changed, 187 insertions(+), 215 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index cafe26b528..ab677e1108 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -234,27 +234,71 @@ void BufferLayer::setPerFrameData(const sp& display) { const auto& viewport = display->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); const auto displayId = display->getId(); + if (!hasHwcLayer(displayId)) { + ALOGE("[%s] failed to setPerFrameData: no HWC layer found (%d)", + mName.string(), displayId); + return; + } + auto& hwcInfo = getBE().mHwcLayers[displayId]; + 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(error)); + visible.dump(LOG_TAG); + } getBE().compositionInfo.hwc.visibleRegion = visible; + + 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(error)); + surfaceDamageRegion.dump(LOG_TAG); + } getBE().compositionInfo.hwc.surfaceDamage = surfaceDamageRegion; // Sideband layers if (getBE().compositionInfo.hwc.sidebandStream.get()) { setCompositionType(displayId, HWC2::Composition::Sideband); + ALOGV("[%s] Requesting Sideband composition", mName.string()); + error = hwcLayer->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle()); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(), + getBE().compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(), + static_cast(error)); + } getBE().compositionInfo.compositionType = HWC2::Composition::Sideband; return; } - if (getBE().compositionInfo.hwc.skipGeometry) { - // Device or Cursor layers - if (mPotentialCursor) { - ALOGV("[%s] Requesting Cursor composition", mName.string()); - setCompositionType(displayId, HWC2::Composition::Cursor); - } else { - ALOGV("[%s] Requesting Device composition", mName.string()); - setCompositionType(displayId, HWC2::Composition::Device); - } + // Device or Cursor layers + if (mPotentialCursor) { + ALOGV("[%s] Requesting Cursor composition", mName.string()); + setCompositionType(displayId, HWC2::Composition::Cursor); + } else { + ALOGV("[%s] Requesting Device composition", mName.string()); + setCompositionType(displayId, HWC2::Composition::Device); + } + + ALOGV("setPerFrameData: dataspace = %d", mCurrentDataSpace); + error = hwcLayer->setDataspace(mCurrentDataSpace); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace, + to_string(error).c_str(), static_cast(error)); } + const HdrMetadata& metadata = getDrawingHdrMetadata(); + error = hwcLayer->setPerFrameMetadata(display->getSupportedPerFrameMetadata(), metadata); + if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) { + ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), + to_string(error).c_str(), static_cast(error)); + } + + error = hwcLayer->setColorTransform(getColorTransform()); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to setColorTransform: %s (%d)", mName.string(), + to_string(error).c_str(), static_cast(error)); + } getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace; getBE().compositionInfo.hwc.hdrMetadata = getDrawingHdrMetadata(); getBE().compositionInfo.hwc.supportedPerFrameMetadata = display->getSupportedPerFrameMetadata(); diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index e75fbdf54d..6cbc4c4fa4 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -327,8 +327,22 @@ status_t BufferQueueLayer::updateFrameNumber(nsecs_t latchTime) { return NO_ERROR; } -void BufferQueueLayer::setHwcLayerBuffer(const sp&) { +void BufferQueueLayer::setHwcLayerBuffer(const sp& display) { + const auto displayId = display->getId(); + auto& hwcInfo = getBE().mHwcLayers[displayId]; + auto& hwcLayer = hwcInfo.layer; + + uint32_t hwcSlot = 0; + sp hwcBuffer; + hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, &hwcSlot, &hwcBuffer); + auto acquireFence = mConsumer->getCurrentFence(); + auto error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), + getBE().compositionInfo.mBuffer->handle, to_string(error).c_str(), + static_cast(error)); + } getBE().compositionInfo.mBufferSlot = mActiveBufferSlot; getBE().compositionInfo.mBuffer = mActiveBuffer; getBE().compositionInfo.hwc.fence = acquireFence; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 3a554c9e44..263f872826 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -62,20 +62,64 @@ void ColorLayer::setPerFrameData(const sp& display) { const auto& viewport = display->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); const auto displayId = display->getId(); + if (!hasHwcLayer(displayId)) { + ALOGE("[%s] failed to setPerFrameData: no HWC layer found (%d)", + mName.string(), displayId); + return; + } + auto& hwcInfo = getBE().mHwcLayers[displayId]; + 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(error)); + visible.dump(LOG_TAG); + } getBE().compositionInfo.hwc.visibleRegion = visible; - getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace; setCompositionType(displayId, HWC2::Composition::SolidColor); + + error = hwcLayer->setDataspace(mCurrentDataSpace); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace, + to_string(error).c_str(), static_cast(error)); + } getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace; half4 color = getColor(); - getBE().compositionInfo.hwc.color = {static_cast(std::round(255.0f * color.r)), - static_cast(std::round(255.0f * color.g)), - static_cast(std::round(255.0f * color.b)), 255}; + error = hwcLayer->setColor({static_cast(std::round(255.0f * color.r)), + static_cast(std::round(255.0f * color.g)), + static_cast(std::round(255.0f * color.b)), 255}); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set color: %s (%d)", mName.string(), to_string(error).c_str(), + static_cast(error)); + } + getBE().compositionInfo.hwc.color = { static_cast(std::round(255.0f * color.r)), + static_cast(std::round(255.0f * color.g)), + static_cast(std::round(255.0f * color.b)), 255 }; // 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(error)); + } getBE().compositionInfo.hwc.transform = HWC2::Transform::None; + + error = hwcLayer->setColorTransform(getColorTransform()); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to setColorTransform: %s (%d)", mName.string(), + to_string(error).c_str(), static_cast(error)); + } getBE().compositionInfo.hwc.colorTransform = getColorTransform(); + + 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(error)); + surfaceDamageRegion.dump(LOG_TAG); + } + getBE().compositionInfo.hwc.surfaceDamage = surfaceDamageRegion; } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 8afd3b3df4..1f3f91991f 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -457,18 +457,6 @@ void Layer::setGeometry(const sp& display, uint32_t z) { } auto& hwcInfo = getBE().mHwcLayers[displayId]; - // Device or Cursor layers - if (mPotentialCursor) { - ALOGV("[%s] Requesting Cursor composition", mName.string()); - setCompositionType(displayId, HWC2::Composition::Cursor); - } else { - ALOGV("[%s] Requesting Device composition", mName.string()); - setCompositionType(displayId, HWC2::Composition::Device); - } - - // Need to program geometry parts - getBE().compositionInfo.hwc.skipGeometry = false; - // enable this layer hwcInfo.forceClientComposition = false; @@ -476,6 +464,8 @@ void Layer::setGeometry(const sp& display, uint32_t z) { hwcInfo.forceClientComposition = true; } + auto& hwcLayer = hwcInfo.layer; + // this gives us only the "orientation" component of the transform const State& s(getDrawingState()); auto blendMode = HWC2::BlendMode::None; @@ -483,6 +473,12 @@ void Layer::setGeometry(const sp& display, uint32_t z) { 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(error)); getBE().compositionInfo.hwc.blendMode = blendMode; // apply the layer's transform, followed by the display's global transform @@ -522,14 +518,39 @@ void Layer::setGeometry(const sp& display, uint32_t z) { } const ui::Transform& tr = display->getTransform(); 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(error)); + } else { + hwcInfo.displayFrame = transformedFrame; + } getBE().compositionInfo.hwc.displayFrame = transformedFrame; FloatRect sourceCrop = computeCrop(display); + 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(error)); + } else { + hwcInfo.sourceCrop = sourceCrop; + } getBE().compositionInfo.hwc.sourceCrop = sourceCrop; float alpha = static_cast(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(error)); getBE().compositionInfo.hwc.alpha = alpha; + 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(error)); getBE().compositionInfo.hwc.z = z; int type = s.type; @@ -543,6 +564,10 @@ void Layer::setGeometry(const sp& display, uint32_t z) { } } + error = hwcLayer->setInfo(type, appId); + ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)", mName.string(), + static_cast(error)); + getBE().compositionInfo.hwc.type = type; getBE().compositionInfo.hwc.appId = appId; @@ -582,9 +607,16 @@ void Layer::setGeometry(const sp& display, uint32_t z) { if (orientation & ui::Transform::ROT_INVALID) { // we can only handle simple transformation hwcInfo.forceClientComposition = true; + getBE().mHwcLayers[displayId].compositionType = HWC2::Composition::Client; } else { auto transform = static_cast(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(error)); getBE().compositionInfo.hwc.transform = transform; } } @@ -665,16 +697,25 @@ void Layer::clearWithOpenGL(const RenderArea& renderArea) const { clearWithOpenGL(renderArea, 0, 0, 0, 0); } -void Layer::setCompositionType(int32_t displayId, HWC2::Composition type, bool /*callIntoHwc*/) { +void Layer::setCompositionType(int32_t displayId, HWC2::Composition type, bool callIntoHwc) { if (getBE().mHwcLayers.count(displayId) == 0) { ALOGE("setCompositionType called without a valid HWC layer"); return; - } else { - if (getBE().mHwcLayers[displayId].compositionType != type) { - ALOGV("setCompositionType: Changing compositionType from %s to %s", - to_string(getBE().mHwcLayers[displayId].compositionType).c_str(), - to_string(type).c_str()); - getBE().mHwcLayers[displayId].compositionType = type; + } + auto& hwcInfo = getBE().mHwcLayers[displayId]; + auto& hwcLayer = hwcInfo.layer; + ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", (hwcLayer)->getId(), to_string(type).c_str(), + static_cast(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(error)); } } } diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp index c9b793377a..70b00dd22a 100644 --- a/services/surfaceflinger/LayerBE.cpp +++ b/services/surfaceflinger/LayerBE.cpp @@ -65,9 +65,7 @@ LayerBE::LayerBE(const LayerBE& layer) } void LayerBE::onLayerDisplayed(const sp& releaseFence) { - if (mLayer) { - mLayer->onLayerDisplayed(releaseFence); - } + mLayer->onLayerDisplayed(releaseFence); } void LayerBE::clear(renderengine::RenderEngine& engine) { diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index d63d16f59e..463c46c285 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -34,14 +34,13 @@ class LayerBE; struct CompositionInfo { std::string layerName; - HWC2::Composition compositionType = HWC2::Composition::Invalid; + HWC2::Composition compositionType; bool firstClear = false; sp mBuffer = nullptr; int mBufferSlot = BufferQueue::INVALID_BUFFER_SLOT; std::shared_ptr layer; struct { std::shared_ptr hwcLayer; - bool skipGeometry = true; int32_t displayId = -1; sp fence; HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f0723e897b..87d8db7397 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1522,13 +1522,8 @@ void SurfaceFlinger::handleMessageRefresh() { preComposition(); rebuildLayerStacks(); calculateWorkingSet(); - for (const auto& [token, display] : mDisplays) { - const auto displayId = display->getId(); beginFrame(display); - for (auto& compositionInfo : getBE().mCompositionInfo[displayId]) { - setUpHWComposer(compositionInfo); - } prepareFrame(display); doDebugFlashRegions(display, repaintEverything); doComposition(display, repaintEverything); @@ -2081,127 +2076,6 @@ void SurfaceFlinger::pickColorMode(const sp& display, ColorMode* display->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent); } -void SurfaceFlinger::configureSidebandComposition(const CompositionInfo& compositionInfo) const -{ - HWC2::Error error; - LOG_ALWAYS_FATAL_IF(compositionInfo.hwc.sidebandStream == nullptr, - "CompositionType is sideband, but sideband stream is nullptr"); - error = (compositionInfo.hwc.hwcLayer) - ->setSidebandStream(compositionInfo.hwc.sidebandStream->handle()); - if (error != HWC2::Error::None) { - ALOGE("[SF] Failed to set sideband stream %p: %s (%d)", - compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(), - static_cast(error)); - } -} - -void SurfaceFlinger::configureHwcCommonData(const CompositionInfo& compositionInfo) const -{ - HWC2::Error error; - - if (!compositionInfo.hwc.skipGeometry) { - error = (compositionInfo.hwc.hwcLayer)->setBlendMode(compositionInfo.hwc.blendMode); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set blend mode %s:" - " %s (%d)", - to_string(compositionInfo.hwc.blendMode).c_str(), to_string(error).c_str(), - static_cast(error)); - - error = (compositionInfo.hwc.hwcLayer)->setDisplayFrame(compositionInfo.hwc.displayFrame); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set the display frame [%d, %d, %d, %d] %s (%d)", - compositionInfo.hwc.displayFrame.left, - compositionInfo.hwc.displayFrame.right, - compositionInfo.hwc.displayFrame.top, - compositionInfo.hwc.displayFrame.bottom, - to_string(error).c_str(), static_cast(error)); - - error = (compositionInfo.hwc.hwcLayer)->setSourceCrop(compositionInfo.hwc.sourceCrop); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: %s (%d)", - compositionInfo.hwc.sourceCrop.left, - compositionInfo.hwc.sourceCrop.right, - compositionInfo.hwc.sourceCrop.top, - compositionInfo.hwc.sourceCrop.bottom, - to_string(error).c_str(), static_cast(error)); - - error = (compositionInfo.hwc.hwcLayer)->setPlaneAlpha(compositionInfo.hwc.alpha); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set plane alpha %.3f: " - "%s (%d)", - compositionInfo.hwc.alpha, - to_string(error).c_str(), static_cast(error)); - - - error = (compositionInfo.hwc.hwcLayer)->setZOrder(compositionInfo.hwc.z); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set Z %u: %s (%d)", - compositionInfo.hwc.z, - to_string(error).c_str(), static_cast(error)); - - error = (compositionInfo.hwc.hwcLayer) - ->setInfo(compositionInfo.hwc.type, compositionInfo.hwc.appId); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set info (%d)", - static_cast(error)); - - error = (compositionInfo.hwc.hwcLayer)->setTransform(compositionInfo.hwc.transform); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set transform %s: " - "%s (%d)", - to_string(compositionInfo.hwc.transform).c_str(), to_string(error).c_str(), - static_cast(error)); - } - - error = (compositionInfo.hwc.hwcLayer)->setCompositionType(compositionInfo.compositionType); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set composition type: %s (%d)", - to_string(error).c_str(), static_cast(error)); - - error = (compositionInfo.hwc.hwcLayer)->setDataspace(compositionInfo.hwc.dataspace); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set dataspace: %s (%d)", - to_string(error).c_str(), static_cast(error)); - - error = (compositionInfo.hwc.hwcLayer)->setPerFrameMetadata( - compositionInfo.hwc.supportedPerFrameMetadata, compositionInfo.hwc.hdrMetadata); - ALOGE_IF(error != HWC2::Error::None && error != HWC2::Error::Unsupported, - "[SF] Failed to set hdrMetadata: %s (%d)", - to_string(error).c_str(), static_cast(error)); - - if (compositionInfo.compositionType == HWC2::Composition::SolidColor) { - error = (compositionInfo.hwc.hwcLayer)->setColor(compositionInfo.hwc.color); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set color: %s (%d)", - to_string(error).c_str(), static_cast(error)); - } - - error = (compositionInfo.hwc.hwcLayer)->setVisibleRegion(compositionInfo.hwc.visibleRegion); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set visible region: %s (%d)", - to_string(error).c_str(), static_cast(error)); - - error = (compositionInfo.hwc.hwcLayer)->setSurfaceDamage(compositionInfo.hwc.surfaceDamage); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set surface damage: %s (%d)", - to_string(error).c_str(), static_cast(error)); - - error = (compositionInfo.hwc.hwcLayer)->setColorTransform(compositionInfo.hwc.colorTransform); -} - -void SurfaceFlinger::configureDeviceComposition(const CompositionInfo& compositionInfo) const -{ - HWC2::Error error; - - if (compositionInfo.hwc.fence) { - error = (compositionInfo.hwc.hwcLayer)->setBuffer(compositionInfo.mBufferSlot, - compositionInfo.mBuffer, compositionInfo.hwc.fence); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set buffer: %s (%d)", - to_string(error).c_str(), static_cast(error)); - } -} - void SurfaceFlinger::beginFrame(const sp& display) { bool dirty = !display->getDirtyRegion(false).isEmpty(); @@ -2247,42 +2121,6 @@ void SurfaceFlinger::prepareFrame(const sp& display) display->getId(), result, strerror(-result)); } -void SurfaceFlinger::setUpHWComposer(const CompositionInfo& compositionInfo) { - ATRACE_CALL(); - ALOGV("setUpHWComposer"); - - switch (compositionInfo.compositionType) - { - case HWC2::Composition::Invalid: - break; - - case HWC2::Composition::Client: - if (compositionInfo.hwc.hwcLayer) { - auto error = (compositionInfo.hwc.hwcLayer)-> - setCompositionType(compositionInfo.compositionType); - ALOGE_IF(error != HWC2::Error::None, - "[SF] Failed to set composition type: %s (%d)", - to_string(error).c_str(), static_cast(error)); - } - break; - - case HWC2::Composition::Sideband: - configureHwcCommonData(compositionInfo); - configureSidebandComposition(compositionInfo); - break; - - case HWC2::Composition::SolidColor: - configureHwcCommonData(compositionInfo); - break; - - case HWC2::Composition::Device: - case HWC2::Composition::Cursor: - configureHwcCommonData(compositionInfo); - configureDeviceComposition(compositionInfo); - break; - } -} - void SurfaceFlinger::doComposition(const sp& display, bool repaintEverything) { ATRACE_CALL(); ALOGV("doComposition"); @@ -2325,14 +2163,15 @@ void SurfaceFlinger::postFramebuffer(const sp& display) } display->onSwapBuffersCompleted(); display->makeCurrent(); - for (auto& compositionInfo : getBE().mCompositionInfo[displayId]) { + for (auto& layer : display->getVisibleLayersSortedByZ()) { sp releaseFence = Fence::NO_FENCE; + // The layer buffer from the previous frame (if any) is released // by HWC only when the release fence from this frame (if any) is // signaled. Always get the release fence from HWC first. - auto hwcLayer = compositionInfo.hwc.hwcLayer; - if ((displayId >= 0) && hwcLayer) { - releaseFence = getBE().mHwc->getLayerReleaseFence(displayId, hwcLayer.get()); + auto hwcLayer = layer->getHwcLayer(displayId); + if (displayId >= 0) { + releaseFence = getBE().mHwc->getLayerReleaseFence(displayId, hwcLayer); } // If the layer was client composited in the previous frame, we @@ -2340,14 +2179,12 @@ void SurfaceFlinger::postFramebuffer(const sp& display) // Since we do not track that, always merge with the current // client target acquire fence when it is available, even though // this is suboptimal. - if (compositionInfo.compositionType == HWC2::Composition::Client) { + if (layer->getCompositionType(displayId) == HWC2::Composition::Client) { releaseFence = Fence::merge("LayerRelease", releaseFence, display->getClientTargetAcquireFence()); } - if (compositionInfo.layer) { - compositionInfo.layer->onLayerDisplayed(releaseFence); - } + layer->getBE().onLayerDisplayed(releaseFence); } // We've got a list of layers needing fences, that are disjoint with diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index f535c4ed13..658f04e878 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -689,7 +689,6 @@ private: * to prepare the hardware composer */ void prepareFrame(const sp& display); - void setUpHWComposer(const CompositionInfo& compositionInfo); void doComposition(const sp& display, bool repainEverything); void doDebugFlashRegions(const sp& display, bool repaintEverything); void doTracing(const char* where); @@ -806,11 +805,6 @@ private: std::atomic mRepaintEverything{false}; - // helper methods - void configureHwcCommonData(const CompositionInfo& compositionInfo) const; - void configureDeviceComposition(const CompositionInfo& compositionInfo) const; - void configureSidebandComposition(const CompositionInfo& compositionInfo) const; - // constant members (no synchronization needed for access) nsecs_t mBootTime; bool mGpuToCpuSupported; diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 4e403b79ca..3719a3d226 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -42,6 +42,7 @@ namespace android { namespace { using testing::_; +using testing::AtLeast; using testing::ByMove; using testing::DoAll; using testing::IsNull; @@ -514,7 +515,7 @@ struct BaseLayerProperties { // expectations are for appears to make an extra call to them. // TODO: Investigate this extra call EXPECT_CALL(*test->mComposer, setLayerTransform(HWC_DISPLAY, HWC_LAYER, DEFAULT_TRANSFORM)) - .Times(1) + .Times(AtLeast(1)) .RetiresOnSaturation(); } -- cgit v1.2.3-59-g8ed1b From f478f9f70b544d9f93680d6734a1af45bbd7f509 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Mon, 15 Oct 2018 12:43:33 -0700 Subject: SurfaceFlinger: Share ownership of layers between State and Handle. Currently the only strong reference to a Layer is held by their parent or the containing layer stack. Firstly, it means that we can not create a SurfaceControl with a null parent. For example, a media decoding library may wish to offer an unparented SurfaceControl representing the decoding Surface, and allow the consumer to parent it between various SurfaceControls as they wish. Secondly it requires lifetime coordination between various levels of the hierarchy, when adding a child you have to be careful to observe the lifetime of the parent because your BufferQueue may become suddenly abandoned at any point. In this change we switch to a reference counted model, such that the Layer remains valid as long as there is a handle to it. We also end the behavior of passing on BufferQueue abandon to children. Layers are only abandoned/disposed when an explicit call to remove is made, or the last reference is dropped. In this CL we switch the handle to holding a strong pointer. We have the handle and the current state forward their references to the main thread to be dropped. We move the contents of onRemoved to the destructor to ensure they are dropped when the last reference is dropped. A second CL will replace the concept of "onRemovedFromCurrentState" with the concept of parent=null, and remove the explicit destroy method, replacing it with an IPC reparent to null. Bug: 62536731 Bug: 111373437 Bug: 111297488 Test: Transaction_test.cpp Change-Id: I22a6c1b27bdc5c377369e59613b32078d15ab1c2 --- services/surfaceflinger/Layer.cpp | 47 ++++++++----- services/surfaceflinger/Layer.h | 16 ++--- services/surfaceflinger/SurfaceFlinger.cpp | 80 ++++++---------------- services/surfaceflinger/SurfaceFlinger.h | 6 +- services/surfaceflinger/tests/Transaction_test.cpp | 31 +++++++++ 5 files changed, 92 insertions(+), 88 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 8afd3b3df4..9f1c6625f6 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -118,13 +118,20 @@ Layer::~Layer() { c->detachLayer(this); } - for (auto& point : mRemoteSyncPoints) { - point->setTransactionApplied(); - } + mFrameTracker.logAndResetStats(mName); + + // The remote sync points are cleared out when we are + // removed from current state. + Mutex::Autolock lock(mLocalSyncPointMutex); for (auto& point : mLocalSyncPoints) { point->setFrameAvailable(); } - mFrameTracker.logAndResetStats(mName); + + abandon(); + + destroyAllHwcLayers(); + + mFlinger->onLayerDestroyed(); } // --------------------------------------------------------------------------- @@ -139,10 +146,9 @@ Layer::~Layer() { void Layer::onLayerDisplayed(const sp& /*releaseFence*/) {} void Layer::onRemovedFromCurrentState() { - // the layer is removed from SF mCurrentState to mLayersPendingRemoval - - mPendingRemoval = true; + mRemovedFromCurrentState = true; + // the layer is removed from SF mCurrentState to mLayersPendingRemoval if (mCurrentState.zOrderRelativeOf != nullptr) { sp strongRelative = mCurrentState.zOrderRelativeOf.promote(); if (strongRelative != nullptr) { @@ -152,19 +158,18 @@ void Layer::onRemovedFromCurrentState() { mCurrentState.zOrderRelativeOf = nullptr; } - for (const auto& child : mCurrentChildren) { - child->onRemovedFromCurrentState(); + // Since we are no longer reachable from CurrentState SurfaceFlinger + // will no longer invoke doTransaction for us, and so we will + // never finish applying transactions. We signal the sync point + // now so that another layer will not become indefinitely + // blocked. + for (auto& point: mRemoteSyncPoints) { + point->setTransactionApplied(); } -} - -void Layer::onRemoved() { - // the layer is removed from SF mLayersPendingRemoval - abandon(); - - destroyAllHwcLayers(); + mRemoteSyncPoints.clear(); for (const auto& child : mCurrentChildren) { - child->onRemoved(); + child->onRemovedFromCurrentState(); } } @@ -227,6 +232,10 @@ void Layer::destroyAllHwcLayers() { } LOG_ALWAYS_FATAL_IF(!getBE().mHwcLayers.empty(), "All hardware composer layers should have been destroyed"); + + for (const sp& child : mDrawingChildren) { + child->destroyAllHwcLayers(); + } } Rect Layer::getContentCrop() const { @@ -783,7 +792,9 @@ void Layer::pushPendingState() { // If this transaction is waiting on the receipt of a frame, generate a sync // point and send it to the remote layer. - if (mCurrentState.barrierLayer_legacy != nullptr) { + // We don't allow installing sync points after we are removed from the current state + // as we won't be able to signal our end. + if (mCurrentState.barrierLayer_legacy != nullptr && !mRemovedFromCurrentState) { sp barrierLayer = mCurrentState.barrierLayer_legacy.promote(); if (barrierLayer == nullptr) { ALOGE("[%s] Unable to promote barrier Layer.", mName.string()); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index e2d1178892..fdec0f71c0 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -345,7 +345,7 @@ public: virtual bool isCreatedFromMainThread() const { return false; } - bool isPendingRemoval() const { return mPendingRemoval; } + bool isRemovedFromCurrentState() const { return mRemovedFromCurrentState; } void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing); @@ -474,12 +474,6 @@ public: */ void onRemovedFromCurrentState(); - /* - * called with the state lock from the main thread when the layer is - * removed from the pending removal list - */ - void onRemoved(); - // Updates the transform hint in our SurfaceFlingerConsumer to match // the current orientation of the display device. void updateTransformHint(const sp& display) const; @@ -594,12 +588,12 @@ protected: */ class LayerCleaner { sp mFlinger; - wp mLayer; + sp mLayer; protected: ~LayerCleaner() { // destroy client resources - mFlinger->onLayerDestroyed(mLayer); + mFlinger->onHandleDestroyed(mLayer); } public: @@ -701,6 +695,8 @@ public: virtual PixelFormat getPixelFormat() const { return PIXEL_FORMAT_NONE; } bool getPremultipledAlpha() const; + bool mPendingHWCDestroy{false}; + protected: // ----------------------------------------------------------------------- bool usingRelativeZ(LayerVector::StateSet stateSet); @@ -744,7 +740,7 @@ protected: // Whether filtering is needed b/c of the drawingstate bool mNeedsFiltering{false}; - bool mPendingRemoval{false}; + bool mRemovedFromCurrentState{false}; // page-flip thread (currently main thread) bool mProtectedByApp{false}; // application requires protected path to external sink diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f0723e897b..badfc6b1bc 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2878,7 +2878,14 @@ void SurfaceFlinger::commitTransaction() for (const auto& l : mLayersPendingRemoval) { recordBufferingStats(l->getName().string(), l->getOccupancyHistory(true)); - l->onRemoved(); + + // We need to release the HWC layers when the Layer is removed + // from the current state otherwise the HWC layer just continues + // showing at it's last configured state until we eventually + // abandon the buffer queue. + if (l->isRemovedFromCurrentState()) { + l->destroyAllHwcLayers(); + } } mLayersPendingRemoval.clear(); } @@ -3311,10 +3318,6 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, if (parent == nullptr) { mCurrentState.layersSortedByZ.add(lbc); } else { - if (parent->isPendingRemoval()) { - ALOGE("addClientLayer called with a removed parent"); - return NAME_NOT_FOUND; - } parent->addChild(lbc); } @@ -3341,52 +3344,22 @@ status_t SurfaceFlinger::removeLayer(const sp& layer, bool topLevelOnly) return removeLayerLocked(mStateLock, layer, topLevelOnly); } -status_t SurfaceFlinger::removeLayerLocked(const Mutex&, const sp& layer, +status_t SurfaceFlinger::removeLayerLocked(const Mutex& lock, const sp& layer, bool topLevelOnly) { - if (layer->isPendingRemoval()) { - return NO_ERROR; - } - const auto& p = layer->getParent(); ssize_t index; if (p != nullptr) { if (topLevelOnly) { return NO_ERROR; } - - sp ancestor = p; - while (ancestor->getParent() != nullptr) { - ancestor = ancestor->getParent(); - } - if (mCurrentState.layersSortedByZ.indexOf(ancestor) < 0) { - ALOGE("removeLayer called with a layer whose parent has been removed"); - return NAME_NOT_FOUND; - } - index = p->removeChild(layer); } else { index = mCurrentState.layersSortedByZ.remove(layer); } - // As a matter of normal operation, the LayerCleaner will produce a second - // attempt to remove the surface. The Layer will be kept alive in mDrawingState - // so we will succeed in promoting it, but it's already been removed - // from mCurrentState. As long as we can find it in mDrawingState we have no problem - // otherwise something has gone wrong and we are leaking the layer. - if (index < 0 && mDrawingState.layersSortedByZ.indexOf(layer) < 0) { - ALOGE("Failed to find layer (%s) in layer parent (%s).", - layer->getName().string(), - (p != nullptr) ? p->getName().string() : "no-parent"); - return BAD_VALUE; - } else if (index < 0) { - return NO_ERROR; - } - layer->onRemovedFromCurrentState(); - mLayersPendingRemoval.add(layer); - mLayersRemoved = true; - mNumLayers -= 1 + layer->getChildrenCount(); - setTransactionFlags(eTransactionNeeded); + + markLayerPendingRemovalLocked(lock, layer); return NO_ERROR; } @@ -3587,11 +3560,6 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState return 0; } - if (layer->isPendingRemoval()) { - ALOGW("Attempting to set client state on removed layer: %s", layer->getName().string()); - return 0; - } - uint32_t flags = 0; const uint32_t what = s.what; @@ -3795,11 +3763,6 @@ void SurfaceFlinger::setDestroyStateLocked(const ComposerState& composerState) { return; } - if (layer->isPendingRemoval()) { - ALOGW("Attempting to destroy on removed layer: %s", layer->getName().string()); - return; - } - if (state.what & layer_state_t::eDestroySurface) { removeLayerLocked(mStateLock, layer); } @@ -3972,17 +3935,16 @@ status_t SurfaceFlinger::onLayerRemoved(const sp& client, const sp& layer) +void SurfaceFlinger::markLayerPendingRemovalLocked(const Mutex&, const sp& layer) { + mLayersPendingRemoval.add(layer); + mLayersRemoved = true; + setTransactionFlags(eTransactionNeeded); +} + +void SurfaceFlinger::onHandleDestroyed(const sp& layer) { - // called by ~LayerCleaner() when all references to the IBinder (handle) - // are gone - sp l = layer.promote(); - if (l == nullptr) { - // The layer has already been removed, carry on - return NO_ERROR; - } - // If we have a parent, then we can continue to live as long as it does. - return removeLayer(l, true); + Mutex::Autolock lock(mStateLock); + markLayerPendingRemovalLocked(mStateLock, layer); } // --------------------------------------------------------------------------- @@ -5375,7 +5337,7 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, auto layerHandle = reinterpret_cast(layerHandleBinder.get()); auto parent = layerHandle->owner.promote(); - if (parent == nullptr || parent->isPendingRemoval()) { + if (parent == nullptr || parent->isRemovedFromCurrentState()) { ALOGE("captureLayers called with a removed parent"); return NAME_NOT_FOUND; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index f535c4ed13..f72bb655e3 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -356,6 +356,8 @@ public: bool authenticateSurfaceTextureLocked( const sp& bufferProducer) const; + inline void onLayerDestroyed() { mNumLayers--; } + private: friend class Client; friend class DisplayEventConnection; @@ -561,10 +563,12 @@ private: // ISurfaceComposerClient::destroySurface() status_t onLayerRemoved(const sp& client, const sp& handle); + void markLayerPendingRemovalLocked(const Mutex& /* mStateLock */, const sp& layer); + // called when all clients have released all their references to // this layer meaning it is entirely safe to destroy all // resources associated to this layer. - status_t onLayerDestroyed(const wp& layer); + void onHandleDestroyed(const sp& layer); // remove a layer from SurfaceFlinger immediately status_t removeLayer(const sp& layer, bool topLevelOnly = false); diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 3166a8c752..df1fee2a00 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -2550,6 +2550,37 @@ TEST_F(ChildLayerTest, ReparentChildren) { } } +TEST_F(ChildLayerTest, ChildrenSurviveParentDestruction) { + sp mGrandChild = + mClient->createSurface(String8("Grand Child"), 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mChild.get()); + fillSurfaceRGBA8(mGrandChild, 111, 111, 111); + + { + SCOPED_TRACE("Grandchild visible"); + ScreenCapture::captureScreen(&mCapture); + mCapture->checkPixel(64, 64, 111, 111, 111); + } + + mChild->clear(); + + { + SCOPED_TRACE("After destroying child"); + ScreenCapture::captureScreen(&mCapture); + mCapture->expectFGColor(64, 64); + } + + asTransaction([&](Transaction& t) { + t.reparent(mGrandChild, mFGSurfaceControl->getHandle()); + }); + + { + SCOPED_TRACE("After reparenting grandchild"); + ScreenCapture::captureScreen(&mCapture); + mCapture->checkPixel(64, 64, 111, 111, 111); + } +} + TEST_F(ChildLayerTest, DetachChildrenSameClient) { asTransaction([&](Transaction& t) { t.show(mChild); -- cgit v1.2.3-59-g8ed1b From 10c985e0267871eae57bee99a520a69bf07ae18b Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Tue, 23 Oct 2018 11:17:45 +0000 Subject: Revert "SurfaceFlinger: Share ownership of layers between State and Handle." This reverts commit f478f9f70b544d9f93680d6734a1af45bbd7f509. Reason for revert: Causes presubmit issues. Change-Id: Ibe872baed863a8ee9b9da5722e1671d087ec3a9f Bug: 118257858 Bug: 62536731 Bug: 111373437 Bug: 111297488 --- services/surfaceflinger/Layer.cpp | 47 +++++-------- services/surfaceflinger/Layer.h | 16 +++-- services/surfaceflinger/SurfaceFlinger.cpp | 80 ++++++++++++++++------ services/surfaceflinger/SurfaceFlinger.h | 6 +- services/surfaceflinger/tests/Transaction_test.cpp | 31 --------- 5 files changed, 88 insertions(+), 92 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 9f1c6625f6..8afd3b3df4 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -118,20 +118,13 @@ Layer::~Layer() { c->detachLayer(this); } - mFrameTracker.logAndResetStats(mName); - - // The remote sync points are cleared out when we are - // removed from current state. - Mutex::Autolock lock(mLocalSyncPointMutex); + for (auto& point : mRemoteSyncPoints) { + point->setTransactionApplied(); + } for (auto& point : mLocalSyncPoints) { point->setFrameAvailable(); } - - abandon(); - - destroyAllHwcLayers(); - - mFlinger->onLayerDestroyed(); + mFrameTracker.logAndResetStats(mName); } // --------------------------------------------------------------------------- @@ -146,9 +139,10 @@ Layer::~Layer() { void Layer::onLayerDisplayed(const sp& /*releaseFence*/) {} void Layer::onRemovedFromCurrentState() { - mRemovedFromCurrentState = true; - // the layer is removed from SF mCurrentState to mLayersPendingRemoval + + mPendingRemoval = true; + if (mCurrentState.zOrderRelativeOf != nullptr) { sp strongRelative = mCurrentState.zOrderRelativeOf.promote(); if (strongRelative != nullptr) { @@ -158,18 +152,19 @@ void Layer::onRemovedFromCurrentState() { mCurrentState.zOrderRelativeOf = nullptr; } - // Since we are no longer reachable from CurrentState SurfaceFlinger - // will no longer invoke doTransaction for us, and so we will - // never finish applying transactions. We signal the sync point - // now so that another layer will not become indefinitely - // blocked. - for (auto& point: mRemoteSyncPoints) { - point->setTransactionApplied(); + for (const auto& child : mCurrentChildren) { + child->onRemovedFromCurrentState(); } - mRemoteSyncPoints.clear(); +} + +void Layer::onRemoved() { + // the layer is removed from SF mLayersPendingRemoval + abandon(); + + destroyAllHwcLayers(); for (const auto& child : mCurrentChildren) { - child->onRemovedFromCurrentState(); + child->onRemoved(); } } @@ -232,10 +227,6 @@ void Layer::destroyAllHwcLayers() { } LOG_ALWAYS_FATAL_IF(!getBE().mHwcLayers.empty(), "All hardware composer layers should have been destroyed"); - - for (const sp& child : mDrawingChildren) { - child->destroyAllHwcLayers(); - } } Rect Layer::getContentCrop() const { @@ -792,9 +783,7 @@ void Layer::pushPendingState() { // If this transaction is waiting on the receipt of a frame, generate a sync // point and send it to the remote layer. - // We don't allow installing sync points after we are removed from the current state - // as we won't be able to signal our end. - if (mCurrentState.barrierLayer_legacy != nullptr && !mRemovedFromCurrentState) { + if (mCurrentState.barrierLayer_legacy != nullptr) { sp barrierLayer = mCurrentState.barrierLayer_legacy.promote(); if (barrierLayer == nullptr) { ALOGE("[%s] Unable to promote barrier Layer.", mName.string()); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index fdec0f71c0..e2d1178892 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -345,7 +345,7 @@ public: virtual bool isCreatedFromMainThread() const { return false; } - bool isRemovedFromCurrentState() const { return mRemovedFromCurrentState; } + bool isPendingRemoval() const { return mPendingRemoval; } void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing); @@ -474,6 +474,12 @@ public: */ void onRemovedFromCurrentState(); + /* + * called with the state lock from the main thread when the layer is + * removed from the pending removal list + */ + void onRemoved(); + // Updates the transform hint in our SurfaceFlingerConsumer to match // the current orientation of the display device. void updateTransformHint(const sp& display) const; @@ -588,12 +594,12 @@ protected: */ class LayerCleaner { sp mFlinger; - sp mLayer; + wp mLayer; protected: ~LayerCleaner() { // destroy client resources - mFlinger->onHandleDestroyed(mLayer); + mFlinger->onLayerDestroyed(mLayer); } public: @@ -695,8 +701,6 @@ public: virtual PixelFormat getPixelFormat() const { return PIXEL_FORMAT_NONE; } bool getPremultipledAlpha() const; - bool mPendingHWCDestroy{false}; - protected: // ----------------------------------------------------------------------- bool usingRelativeZ(LayerVector::StateSet stateSet); @@ -740,7 +744,7 @@ protected: // Whether filtering is needed b/c of the drawingstate bool mNeedsFiltering{false}; - bool mRemovedFromCurrentState{false}; + bool mPendingRemoval{false}; // page-flip thread (currently main thread) bool mProtectedByApp{false}; // application requires protected path to external sink diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index badfc6b1bc..f0723e897b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2878,14 +2878,7 @@ void SurfaceFlinger::commitTransaction() for (const auto& l : mLayersPendingRemoval) { recordBufferingStats(l->getName().string(), l->getOccupancyHistory(true)); - - // We need to release the HWC layers when the Layer is removed - // from the current state otherwise the HWC layer just continues - // showing at it's last configured state until we eventually - // abandon the buffer queue. - if (l->isRemovedFromCurrentState()) { - l->destroyAllHwcLayers(); - } + l->onRemoved(); } mLayersPendingRemoval.clear(); } @@ -3318,6 +3311,10 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, if (parent == nullptr) { mCurrentState.layersSortedByZ.add(lbc); } else { + if (parent->isPendingRemoval()) { + ALOGE("addClientLayer called with a removed parent"); + return NAME_NOT_FOUND; + } parent->addChild(lbc); } @@ -3344,22 +3341,52 @@ status_t SurfaceFlinger::removeLayer(const sp& layer, bool topLevelOnly) return removeLayerLocked(mStateLock, layer, topLevelOnly); } -status_t SurfaceFlinger::removeLayerLocked(const Mutex& lock, const sp& layer, +status_t SurfaceFlinger::removeLayerLocked(const Mutex&, const sp& layer, bool topLevelOnly) { + if (layer->isPendingRemoval()) { + return NO_ERROR; + } + const auto& p = layer->getParent(); ssize_t index; if (p != nullptr) { if (topLevelOnly) { return NO_ERROR; } + + sp ancestor = p; + while (ancestor->getParent() != nullptr) { + ancestor = ancestor->getParent(); + } + if (mCurrentState.layersSortedByZ.indexOf(ancestor) < 0) { + ALOGE("removeLayer called with a layer whose parent has been removed"); + return NAME_NOT_FOUND; + } + index = p->removeChild(layer); } else { index = mCurrentState.layersSortedByZ.remove(layer); } - layer->onRemovedFromCurrentState(); + // As a matter of normal operation, the LayerCleaner will produce a second + // attempt to remove the surface. The Layer will be kept alive in mDrawingState + // so we will succeed in promoting it, but it's already been removed + // from mCurrentState. As long as we can find it in mDrawingState we have no problem + // otherwise something has gone wrong and we are leaking the layer. + if (index < 0 && mDrawingState.layersSortedByZ.indexOf(layer) < 0) { + ALOGE("Failed to find layer (%s) in layer parent (%s).", + layer->getName().string(), + (p != nullptr) ? p->getName().string() : "no-parent"); + return BAD_VALUE; + } else if (index < 0) { + return NO_ERROR; + } - markLayerPendingRemovalLocked(lock, layer); + layer->onRemovedFromCurrentState(); + mLayersPendingRemoval.add(layer); + mLayersRemoved = true; + mNumLayers -= 1 + layer->getChildrenCount(); + setTransactionFlags(eTransactionNeeded); return NO_ERROR; } @@ -3560,6 +3587,11 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState return 0; } + if (layer->isPendingRemoval()) { + ALOGW("Attempting to set client state on removed layer: %s", layer->getName().string()); + return 0; + } + uint32_t flags = 0; const uint32_t what = s.what; @@ -3763,6 +3795,11 @@ void SurfaceFlinger::setDestroyStateLocked(const ComposerState& composerState) { return; } + if (layer->isPendingRemoval()) { + ALOGW("Attempting to destroy on removed layer: %s", layer->getName().string()); + return; + } + if (state.what & layer_state_t::eDestroySurface) { removeLayerLocked(mStateLock, layer); } @@ -3935,16 +3972,17 @@ status_t SurfaceFlinger::onLayerRemoved(const sp& client, const sp& layer) { - mLayersPendingRemoval.add(layer); - mLayersRemoved = true; - setTransactionFlags(eTransactionNeeded); -} - -void SurfaceFlinger::onHandleDestroyed(const sp& layer) +status_t SurfaceFlinger::onLayerDestroyed(const wp& layer) { - Mutex::Autolock lock(mStateLock); - markLayerPendingRemovalLocked(mStateLock, layer); + // called by ~LayerCleaner() when all references to the IBinder (handle) + // are gone + sp l = layer.promote(); + if (l == nullptr) { + // The layer has already been removed, carry on + return NO_ERROR; + } + // If we have a parent, then we can continue to live as long as it does. + return removeLayer(l, true); } // --------------------------------------------------------------------------- @@ -5337,7 +5375,7 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, auto layerHandle = reinterpret_cast(layerHandleBinder.get()); auto parent = layerHandle->owner.promote(); - if (parent == nullptr || parent->isRemovedFromCurrentState()) { + if (parent == nullptr || parent->isPendingRemoval()) { ALOGE("captureLayers called with a removed parent"); return NAME_NOT_FOUND; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index f72bb655e3..f535c4ed13 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -356,8 +356,6 @@ public: bool authenticateSurfaceTextureLocked( const sp& bufferProducer) const; - inline void onLayerDestroyed() { mNumLayers--; } - private: friend class Client; friend class DisplayEventConnection; @@ -563,12 +561,10 @@ private: // ISurfaceComposerClient::destroySurface() status_t onLayerRemoved(const sp& client, const sp& handle); - void markLayerPendingRemovalLocked(const Mutex& /* mStateLock */, const sp& layer); - // called when all clients have released all their references to // this layer meaning it is entirely safe to destroy all // resources associated to this layer. - void onHandleDestroyed(const sp& layer); + status_t onLayerDestroyed(const wp& layer); // remove a layer from SurfaceFlinger immediately status_t removeLayer(const sp& layer, bool topLevelOnly = false); diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index df1fee2a00..3166a8c752 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -2550,37 +2550,6 @@ TEST_F(ChildLayerTest, ReparentChildren) { } } -TEST_F(ChildLayerTest, ChildrenSurviveParentDestruction) { - sp mGrandChild = - mClient->createSurface(String8("Grand Child"), 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mChild.get()); - fillSurfaceRGBA8(mGrandChild, 111, 111, 111); - - { - SCOPED_TRACE("Grandchild visible"); - ScreenCapture::captureScreen(&mCapture); - mCapture->checkPixel(64, 64, 111, 111, 111); - } - - mChild->clear(); - - { - SCOPED_TRACE("After destroying child"); - ScreenCapture::captureScreen(&mCapture); - mCapture->expectFGColor(64, 64); - } - - asTransaction([&](Transaction& t) { - t.reparent(mGrandChild, mFGSurfaceControl->getHandle()); - }); - - { - SCOPED_TRACE("After reparenting grandchild"); - ScreenCapture::captureScreen(&mCapture); - mCapture->checkPixel(64, 64, 111, 111, 111); - } -} - TEST_F(ChildLayerTest, DetachChildrenSameClient) { asTransaction([&](Transaction& t) { t.show(mChild); -- cgit v1.2.3-59-g8ed1b From 9689e2f6cefc158a493ff58ccacda0333f823939 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Fri, 11 May 2018 12:33:23 -0700 Subject: SF TimeStats: optimize mTimeStatsTracker to use layerID as hash key The current mTimeStatsTracker map is using layer name as the hash key, which is not as fast and reliable as the unique layer sequence id. Test: dumpsys SurfaceFlinger --timestats Bug: b/79872109 Change-Id: I409414909e7dd7ee11b37a35a441c070cfce3fa6 --- services/surfaceflinger/BufferLayer.cpp | 10 +- services/surfaceflinger/BufferQueueLayer.cpp | 12 +- services/surfaceflinger/BufferStateLayer.cpp | 22 ++-- services/surfaceflinger/Layer.cpp | 7 +- services/surfaceflinger/TimeStats/TimeStats.cpp | 154 ++++++++++++------------ services/surfaceflinger/TimeStats/TimeStats.h | 31 ++--- 6 files changed, 123 insertions(+), 113 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index a0a07ec48e..397540a532 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -71,7 +71,7 @@ BufferLayer::~BufferLayer() { destroyAllHwcLayers(); } - mTimeStats.onDestroy(getName().c_str()); + mTimeStats.onDestroy(getSequence()); } void BufferLayer::useSurfaceDamage() { @@ -293,8 +293,8 @@ bool BufferLayer::onPostComposition(const std::shared_ptr& glDoneFenc nsecs_t desiredPresentTime = getDesiredPresentTime(); mFrameTracker.setDesiredPresentTime(desiredPresentTime); - const std::string layerName(getName().c_str()); - mTimeStats.setDesiredTime(layerName, mCurrentFrameNumber, desiredPresentTime); + const int32_t layerID = getSequence(); + mTimeStats.setDesiredTime(layerID, mCurrentFrameNumber, desiredPresentTime); std::shared_ptr frameReadyFence = getCurrentFenceTime(); if (frameReadyFence->isValid()) { @@ -306,14 +306,14 @@ bool BufferLayer::onPostComposition(const std::shared_ptr& glDoneFenc } if (presentFence->isValid()) { - mTimeStats.setPresentFence(layerName, mCurrentFrameNumber, presentFence); + mTimeStats.setPresentFence(layerID, mCurrentFrameNumber, presentFence); mFrameTracker.setActualPresentFence(std::shared_ptr(presentFence)); } else if (mFlinger->getHwComposer().isConnected(HWC_DISPLAY_PRIMARY)) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(HWC_DISPLAY_PRIMARY); - mTimeStats.setPresentTime(layerName, mCurrentFrameNumber, actualPresentTime); + mTimeStats.setPresentTime(layerID, mCurrentFrameNumber, actualPresentTime); mFrameTracker.setActualPresentTime(actualPresentTime); } diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index e75fbdf54d..ca3859eb8d 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -227,6 +227,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t // BufferItem's that weren't actually queued. This can happen in shared // buffer mode. bool queuedBuffer = false; + const int32_t layerID = getSequence(); LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions, getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode, getTransformToDisplayInverse(), mFreezeGeometryUpdates); @@ -247,7 +248,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t // and return early if (queuedBuffer) { Mutex::Autolock lock(mQueueItemLock); - mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber); + mTimeStats.removeTimeRecord(layerID, mQueueItems[0].mFrameNumber); mQueueItems.removeAt(0); mQueuedFrames--; } @@ -261,7 +262,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t Mutex::Autolock lock(mQueueItemLock); mQueueItems.clear(); mQueuedFrames = 0; - mTimeStats.clearLayerRecord(getName().c_str()); + mTimeStats.clearLayerRecord(layerID); } // Once we have hit this state, the shadow queue may no longer @@ -282,14 +283,13 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t // Remove any stale buffers that have been dropped during // updateTexImage while (mQueueItems[0].mFrameNumber != currentFrameNumber) { - mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber); + mTimeStats.removeTimeRecord(layerID, mQueueItems[0].mFrameNumber); mQueueItems.removeAt(0); mQueuedFrames--; } - const std::string layerName(getName().c_str()); - mTimeStats.setAcquireFence(layerName, currentFrameNumber, mQueueItems[0].mFenceTime); - mTimeStats.setLatchTime(layerName, currentFrameNumber, latchTime); + mTimeStats.setAcquireFence(layerID, currentFrameNumber, mQueueItems[0].mFenceTime); + mTimeStats.setLatchTime(layerID, currentFrameNumber, latchTime); mQueueItems.removeAt(0); } diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index e52b35a135..5df8ade34e 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -377,6 +377,8 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse return NO_ERROR; } + const int32_t layerID = getSequence(); + // Reject if the layer is invalid uint32_t bufferWidth = s.buffer->width; uint32_t bufferHeight = s.buffer->height; @@ -397,7 +399,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse ALOGE("[%s] rejecting buffer: " "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}", mName.string(), bufferWidth, bufferHeight, s.active.w, s.active.h); - mTimeStats.removeTimeRecord(getName().c_str(), getFrameNumber()); + mTimeStats.removeTimeRecord(layerID, getFrameNumber()); return BAD_VALUE; } @@ -405,7 +407,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse if (SyncFeatures::getInstance().useNativeFenceSync() && releaseFence != Fence::NO_FENCE) { // TODO(alecmouri): Fail somewhere upstream if the fence is invalid. if (!releaseFence->isValid()) { - mTimeStats.clearLayerRecord(getName().c_str()); + mTimeStats.clearLayerRecord(layerID); return UNKNOWN_ERROR; } @@ -415,7 +417,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse auto currentStatus = s.acquireFence->getStatus(); if (currentStatus == Fence::Status::Invalid) { ALOGE("Existing fence has invalid state"); - mTimeStats.clearLayerRecord(getName().c_str()); + mTimeStats.clearLayerRecord(layerID); return BAD_VALUE; } @@ -423,7 +425,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse if (incomingStatus == Fence::Status::Invalid) { ALOGE("New fence has invalid state"); mDrawingState.acquireFence = releaseFence; - mTimeStats.clearLayerRecord(getName().c_str()); + mTimeStats.clearLayerRecord(layerID); return BAD_VALUE; } @@ -439,7 +441,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse // synchronization is broken, the best we can do is hope fences // signal in order so the new fence will act like a union mDrawingState.acquireFence = releaseFence; - mTimeStats.clearLayerRecord(getName().c_str()); + mTimeStats.clearLayerRecord(layerID); return BAD_VALUE; } mDrawingState.acquireFence = mergedFence; @@ -462,16 +464,16 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse // a GL-composited layer) not at all. status_t err = bindTextureImage(); if (err != NO_ERROR) { - mTimeStats.clearLayerRecord(getName().c_str()); + mTimeStats.clearLayerRecord(layerID); return BAD_VALUE; } } // TODO(marissaw): properly support mTimeStats - const std::string layerName(getName().c_str()); - mTimeStats.setPostTime(getName().c_str(), getFrameNumber(), latchTime); - mTimeStats.setAcquireFence(layerName, getFrameNumber(), getCurrentFenceTime()); - mTimeStats.setLatchTime(layerName, getFrameNumber(), latchTime); + mTimeStats.setLayerName(layerID, getName().c_str()); + mTimeStats.setPostTime(layerID, getFrameNumber(), latchTime); + mTimeStats.setAcquireFence(layerID, getFrameNumber(), getCurrentFenceTime()); + mTimeStats.setLatchTime(layerID, getFrameNumber(), latchTime); return NO_ERROR; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 8afd3b3df4..7b9cd0115f 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1428,14 +1428,15 @@ void Layer::dumpFrameEvents(String8& result) { void Layer::onDisconnect() { Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.onDisconnect(); - mTimeStats.onDisconnect(getName().c_str()); + mTimeStats.onDisconnect(getSequence()); } void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, FrameEventHistoryDelta* outDelta) { if (newTimestamps) { - mTimeStats.setPostTime(getName().c_str(), newTimestamps->frameNumber, - newTimestamps->postedTime); + const int32_t layerID = getSequence(); + mTimeStats.setLayerName(layerID, getName().c_str()); + mTimeStats.setPostTime(layerID, newTimestamps->frameNumber, newTimestamps->postedTime); } Mutex::Autolock lock(mFrameEventHistoryMutex); diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp index f754d479db..43fa262045 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.cpp +++ b/services/surfaceflinger/TimeStats/TimeStats.cpp @@ -104,9 +104,9 @@ void TimeStats::incrementClientCompositionFrames() { mTimeStats.clientCompositionFrames++; } -bool TimeStats::recordReadyLocked(const std::string& layerName, TimeRecord* timeRecord) { +bool TimeStats::recordReadyLocked(int32_t layerID, TimeRecord* timeRecord) { if (!timeRecord->ready) { - ALOGV("[%s]-[%" PRIu64 "]-presentFence is still not received", layerName.c_str(), + ALOGV("[%d]-[%" PRIu64 "]-presentFence is still not received", layerID, timeRecord->frameTime.frameNumber); return false; } @@ -119,7 +119,7 @@ bool TimeStats::recordReadyLocked(const std::string& layerName, TimeRecord* time timeRecord->frameTime.acquireTime = timeRecord->acquireFence->getSignalTime(); timeRecord->acquireFence = nullptr; } else { - ALOGV("[%s]-[%" PRIu64 "]-acquireFence signal time is invalid", layerName.c_str(), + ALOGV("[%d]-[%" PRIu64 "]-acquireFence signal time is invalid", layerID, timeRecord->frameTime.frameNumber); } } @@ -132,7 +132,7 @@ bool TimeStats::recordReadyLocked(const std::string& layerName, TimeRecord* time timeRecord->frameTime.presentTime = timeRecord->presentFence->getSignalTime(); timeRecord->presentFence = nullptr; } else { - ALOGV("[%s]-[%" PRIu64 "]-presentFence signal time invalid", layerName.c_str(), + ALOGV("[%d]-[%" PRIu64 "]-presentFence signal time invalid", layerID, timeRecord->frameTime.frameNumber); } } @@ -162,18 +162,19 @@ static std::string getPackageName(const std::string& layerName) { return ""; } -void TimeStats::flushAvailableRecordsToStatsLocked(const std::string& layerName) { +void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerID) { ATRACE_CALL(); - LayerRecord& layerRecord = mTimeStatsTracker[layerName]; + LayerRecord& layerRecord = mTimeStatsTracker[layerID]; TimeRecord& prevTimeRecord = layerRecord.prevTimeRecord; std::deque& timeRecords = layerRecord.timeRecords; while (!timeRecords.empty()) { - if (!recordReadyLocked(layerName, &timeRecords[0])) break; - ALOGV("[%s]-[%" PRIu64 "]-presentFenceTime[%" PRId64 "]", layerName.c_str(), + if (!recordReadyLocked(layerID, &timeRecords[0])) break; + ALOGV("[%d]-[%" PRIu64 "]-presentFenceTime[%" PRId64 "]", layerID, timeRecords[0].frameTime.frameNumber, timeRecords[0].frameTime.presentTime); if (prevTimeRecord.ready) { + const std::string& layerName = layerRecord.layerName; if (!mTimeStats.stats.count(layerName)) { mTimeStats.stats[layerName].layerName = layerName; mTimeStats.stats[layerName].packageName = getPackageName(layerName); @@ -185,37 +186,37 @@ void TimeStats::flushAvailableRecordsToStatsLocked(const std::string& layerName) const int32_t postToAcquireMs = msBetween(timeRecords[0].frameTime.postTime, timeRecords[0].frameTime.acquireTime); - ALOGV("[%s]-[%" PRIu64 "]-post2acquire[%d]", layerName.c_str(), + ALOGV("[%d]-[%" PRIu64 "]-post2acquire[%d]", layerID, timeRecords[0].frameTime.frameNumber, postToAcquireMs); timeStatsLayer.deltas["post2acquire"].insert(postToAcquireMs); const int32_t postToPresentMs = msBetween(timeRecords[0].frameTime.postTime, timeRecords[0].frameTime.presentTime); - ALOGV("[%s]-[%" PRIu64 "]-post2present[%d]", layerName.c_str(), + ALOGV("[%d]-[%" PRIu64 "]-post2present[%d]", layerID, timeRecords[0].frameTime.frameNumber, postToPresentMs); timeStatsLayer.deltas["post2present"].insert(postToPresentMs); const int32_t acquireToPresentMs = msBetween(timeRecords[0].frameTime.acquireTime, timeRecords[0].frameTime.presentTime); - ALOGV("[%s]-[%" PRIu64 "]-acquire2present[%d]", layerName.c_str(), + ALOGV("[%d]-[%" PRIu64 "]-acquire2present[%d]", layerID, timeRecords[0].frameTime.frameNumber, acquireToPresentMs); timeStatsLayer.deltas["acquire2present"].insert(acquireToPresentMs); const int32_t latchToPresentMs = msBetween(timeRecords[0].frameTime.latchTime, timeRecords[0].frameTime.presentTime); - ALOGV("[%s]-[%" PRIu64 "]-latch2present[%d]", layerName.c_str(), + ALOGV("[%d]-[%" PRIu64 "]-latch2present[%d]", layerID, timeRecords[0].frameTime.frameNumber, latchToPresentMs); timeStatsLayer.deltas["latch2present"].insert(latchToPresentMs); const int32_t desiredToPresentMs = msBetween(timeRecords[0].frameTime.desiredTime, timeRecords[0].frameTime.presentTime); - ALOGV("[%s]-[%" PRIu64 "]-desired2present[%d]", layerName.c_str(), + ALOGV("[%d]-[%" PRIu64 "]-desired2present[%d]", layerID, timeRecords[0].frameTime.frameNumber, desiredToPresentMs); timeStatsLayer.deltas["desired2present"].insert(desiredToPresentMs); const int32_t presentToPresentMs = msBetween(prevTimeRecord.frameTime.presentTime, timeRecords[0].frameTime.presentTime); - ALOGV("[%s]-[%" PRIu64 "]-present2present[%d]", layerName.c_str(), + ALOGV("[%d]-[%" PRIu64 "]-present2present[%d]", layerID, timeRecords[0].frameTime.frameNumber, presentToPresentMs); timeStatsLayer.deltas["present2present"].insert(presentToPresentMs); } @@ -240,23 +241,33 @@ static bool layerNameIsValid(const std::string& layerName) { return std::regex_match(layerName.begin(), layerName.end(), layerNameRegex); } -void TimeStats::setPostTime(const std::string& layerName, uint64_t frameNumber, nsecs_t postTime) { +void TimeStats::setLayerName(int32_t layerID, const std::string& layerName) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%s]-[%" PRIu64 "]-PostTime[%" PRId64 "]", layerName.c_str(), frameNumber, postTime); + ALOGV("[%d]-[%s]", layerID, layerName.c_str()); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerName) && !layerNameIsValid(layerName)) { - return; + if (!mTimeStatsTracker.count(layerID) && layerNameIsValid(layerName)) { + mTimeStatsTracker[layerID].layerName = layerName; } - LayerRecord& layerRecord = mTimeStatsTracker[layerName]; +} + +void TimeStats::setPostTime(int32_t layerID, uint64_t frameNumber, nsecs_t postTime) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%d]-[%" PRIu64 "]-PostTime[%" PRId64 "]", layerID, frameNumber, postTime); + + std::lock_guard lock(mMutex); + if (!mTimeStatsTracker.count(layerID)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerID]; if (layerRecord.timeRecords.size() == MAX_NUM_TIME_RECORDS) { - ALOGV("[%s]-timeRecords is already at its maximum size[%zu]", layerName.c_str(), - MAX_NUM_TIME_RECORDS); - // TODO(zzyiwei): if this happens, there must be a present fence missing - // or waitData is not in the correct position. Need to think out a - // reasonable way to recover from this state. + ALOGE("[%d]-[%s]-timeRecords is already at its maximum size[%zu]. Please file a bug.", + layerID, layerRecord.layerName.c_str(), MAX_NUM_TIME_RECORDS); + layerRecord.timeRecords.clear(); + layerRecord.prevTimeRecord.ready = false; + layerRecord.waitData = -1; return; } // For most media content, the acquireFence is invalid because the buffer is @@ -276,84 +287,77 @@ void TimeStats::setPostTime(const std::string& layerName, uint64_t frameNumber, layerRecord.waitData = layerRecord.timeRecords.size() - 1; } -void TimeStats::setLatchTime(const std::string& layerName, uint64_t frameNumber, - nsecs_t latchTime) { +void TimeStats::setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latchTime) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%s]-[%" PRIu64 "]-LatchTime[%" PRId64 "]", layerName.c_str(), frameNumber, latchTime); + ALOGV("[%d]-[%" PRIu64 "]-LatchTime[%" PRId64 "]", layerID, frameNumber, latchTime); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerName)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerName]; + if (!mTimeStatsTracker.count(layerID)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerID]; TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; if (timeRecord.frameTime.frameNumber == frameNumber) { timeRecord.frameTime.latchTime = latchTime; } } -void TimeStats::setDesiredTime(const std::string& layerName, uint64_t frameNumber, - nsecs_t desiredTime) { +void TimeStats::setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t desiredTime) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%s]-[%" PRIu64 "]-DesiredTime[%" PRId64 "]", layerName.c_str(), frameNumber, - desiredTime); + ALOGV("[%d]-[%" PRIu64 "]-DesiredTime[%" PRId64 "]", layerID, frameNumber, desiredTime); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerName)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerName]; + if (!mTimeStatsTracker.count(layerID)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerID]; TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; if (timeRecord.frameTime.frameNumber == frameNumber) { timeRecord.frameTime.desiredTime = desiredTime; } } -void TimeStats::setAcquireTime(const std::string& layerName, uint64_t frameNumber, - nsecs_t acquireTime) { +void TimeStats::setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t acquireTime) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%s]-[%" PRIu64 "]-AcquireTime[%" PRId64 "]", layerName.c_str(), frameNumber, - acquireTime); + ALOGV("[%d]-[%" PRIu64 "]-AcquireTime[%" PRId64 "]", layerID, frameNumber, acquireTime); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerName)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerName]; + if (!mTimeStatsTracker.count(layerID)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerID]; TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; if (timeRecord.frameTime.frameNumber == frameNumber) { timeRecord.frameTime.acquireTime = acquireTime; } } -void TimeStats::setAcquireFence(const std::string& layerName, uint64_t frameNumber, +void TimeStats::setAcquireFence(int32_t layerID, uint64_t frameNumber, const std::shared_ptr& acquireFence) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%s]-[%" PRIu64 "]-AcquireFenceTime[%" PRId64 "]", layerName.c_str(), frameNumber, + ALOGV("[%d]-[%" PRIu64 "]-AcquireFenceTime[%" PRId64 "]", layerID, frameNumber, acquireFence->getSignalTime()); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerName)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerName]; + if (!mTimeStatsTracker.count(layerID)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerID]; TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; if (timeRecord.frameTime.frameNumber == frameNumber) { timeRecord.acquireFence = acquireFence; } } -void TimeStats::setPresentTime(const std::string& layerName, uint64_t frameNumber, - nsecs_t presentTime) { +void TimeStats::setPresentTime(int32_t layerID, uint64_t frameNumber, nsecs_t presentTime) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%s]-[%" PRIu64 "]-PresentTime[%" PRId64 "]", layerName.c_str(), frameNumber, - presentTime); + ALOGV("[%d]-[%" PRIu64 "]-PresentTime[%" PRId64 "]", layerID, frameNumber, presentTime); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerName)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerName]; + if (!mTimeStatsTracker.count(layerID)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerID]; TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; if (timeRecord.frameTime.frameNumber == frameNumber) { timeRecord.frameTime.presentTime = presentTime; @@ -361,20 +365,20 @@ void TimeStats::setPresentTime(const std::string& layerName, uint64_t frameNumbe layerRecord.waitData++; } - flushAvailableRecordsToStatsLocked(layerName); + flushAvailableRecordsToStatsLocked(layerID); } -void TimeStats::setPresentFence(const std::string& layerName, uint64_t frameNumber, +void TimeStats::setPresentFence(int32_t layerID, uint64_t frameNumber, const std::shared_ptr& presentFence) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%s]-[%" PRIu64 "]-PresentFenceTime[%" PRId64 "]", layerName.c_str(), frameNumber, + ALOGV("[%d]-[%" PRIu64 "]-PresentFenceTime[%" PRId64 "]", layerID, frameNumber, presentFence->getSignalTime()); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerName)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerName]; + if (!mTimeStatsTracker.count(layerID)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerID]; TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; if (timeRecord.frameTime.frameNumber == frameNumber) { timeRecord.presentFence = presentFence; @@ -382,57 +386,57 @@ void TimeStats::setPresentFence(const std::string& layerName, uint64_t frameNumb layerRecord.waitData++; } - flushAvailableRecordsToStatsLocked(layerName); + flushAvailableRecordsToStatsLocked(layerID); } -void TimeStats::onDisconnect(const std::string& layerName) { +void TimeStats::onDisconnect(int32_t layerID) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%s]-onDisconnect", layerName.c_str()); + ALOGV("[%d]-onDisconnect", layerID); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerName)) return; - flushAvailableRecordsToStatsLocked(layerName); - mTimeStatsTracker.erase(layerName); + if (!mTimeStatsTracker.count(layerID)) return; + flushAvailableRecordsToStatsLocked(layerID); + mTimeStatsTracker.erase(layerID); } -void TimeStats::onDestroy(const std::string& layerName) { +void TimeStats::onDestroy(int32_t layerID) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%s]-onDestroy", layerName.c_str()); + ALOGV("[%d]-onDestroy", layerID); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerName)) return; - flushAvailableRecordsToStatsLocked(layerName); - mTimeStatsTracker.erase(layerName); + if (!mTimeStatsTracker.count(layerID)) return; + flushAvailableRecordsToStatsLocked(layerID); + mTimeStatsTracker.erase(layerID); } -void TimeStats::clearLayerRecord(const std::string& layerName) { +void TimeStats::clearLayerRecord(int32_t layerID) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%s]-clearLayerRecord", layerName.c_str()); + ALOGV("[%d]-clearLayerRecord", layerID); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerName)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerName]; + if (!mTimeStatsTracker.count(layerID)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerID]; layerRecord.timeRecords.clear(); layerRecord.prevTimeRecord.ready = false; layerRecord.waitData = -1; layerRecord.droppedFrames = 0; } -void TimeStats::removeTimeRecord(const std::string& layerName, uint64_t frameNumber) { +void TimeStats::removeTimeRecord(int32_t layerID, uint64_t frameNumber) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%s]-[%" PRIu64 "]-removeTimeRecord", layerName.c_str(), frameNumber); + ALOGV("[%d]-[%" PRIu64 "]-removeTimeRecord", layerID, frameNumber); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerName)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerName]; + if (!mTimeStatsTracker.count(layerID)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerID]; size_t removeAt = 0; for (const TimeRecord& record : layerRecord.timeRecords) { if (record.frameTime.frameNumber == frameNumber) break; diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h index c78d84e6f3..d1e554cbd2 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.h +++ b/services/surfaceflinger/TimeStats/TimeStats.h @@ -59,6 +59,7 @@ class TimeStats { }; struct LayerRecord { + std::string layerName; // This is the index in timeRecords, at which the timestamps for that // specific frame are still not fully received. This is not waiting for // fences to signal, but rather waiting to receive those fences/timestamps. @@ -85,23 +86,24 @@ public: void incrementMissedFrames(); void incrementClientCompositionFrames(); - void setPostTime(const std::string& layerName, uint64_t frameNumber, nsecs_t postTime); - void setLatchTime(const std::string& layerName, uint64_t frameNumber, nsecs_t latchTime); - void setDesiredTime(const std::string& layerName, uint64_t frameNumber, nsecs_t desiredTime); - void setAcquireTime(const std::string& layerName, uint64_t frameNumber, nsecs_t acquireTime); - void setAcquireFence(const std::string& layerName, uint64_t frameNumber, + void setLayerName(int32_t layerID, const std::string& layerName); + void setPostTime(int32_t layerID, uint64_t frameNumber, nsecs_t postTime); + void setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latchTime); + void setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t desiredTime); + void setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t acquireTime); + void setAcquireFence(int32_t layerID, uint64_t frameNumber, const std::shared_ptr& acquireFence); - void setPresentTime(const std::string& layerName, uint64_t frameNumber, nsecs_t presentTime); - void setPresentFence(const std::string& layerName, uint64_t frameNumber, + void setPresentTime(int32_t layerID, uint64_t frameNumber, nsecs_t presentTime); + void setPresentFence(int32_t layerID, uint64_t frameNumber, const std::shared_ptr& presentFence); // On producer disconnect with BufferQueue. - void onDisconnect(const std::string& layerName); + void onDisconnect(int32_t layerID); // On layer tear down. - void onDestroy(const std::string& layerName); + void onDestroy(int32_t layerID); // When SF is cleaning up the queue, clear the LayerRecord as well. - void clearLayerRecord(const std::string& layerName); + void clearLayerRecord(int32_t layerID); // If SF skips or rejects a buffer, remove the corresponding TimeRecord. - void removeTimeRecord(const std::string& layerName, uint64_t frameNumber); + void removeTimeRecord(int32_t layerID, uint64_t frameNumber); void setPowerMode(int32_t powerMode); void setPresentFenceGlobal(const std::shared_ptr& presentFence); @@ -109,8 +111,8 @@ public: private: TimeStats() = default; - bool recordReadyLocked(const std::string& layerName, TimeRecord* timeRecord); - void flushAvailableRecordsToStatsLocked(const std::string& layerName); + bool recordReadyLocked(int32_t layerID, TimeRecord* timeRecord); + void flushAvailableRecordsToStatsLocked(int32_t layerID); void flushPowerTimeLocked(); void flushAvailableGlobalRecordsToStatsLocked(); @@ -123,7 +125,8 @@ private: std::atomic mEnabled = false; std::mutex mMutex; TimeStatsHelper::TimeStatsGlobal mTimeStats; - std::unordered_map mTimeStatsTracker; + // Hashmap for LayerRecord with layerID as the hash key + std::unordered_map mTimeStatsTracker; PowerTime mPowerTime; GlobalRecord mGlobalRecord; }; -- cgit v1.2.3-59-g8ed1b From 8e8fe529a69761aad6a84fb8025cebd3673d77db Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Fri, 2 Nov 2018 18:34:07 -0700 Subject: SF TimeStats: fix a hazard issue The setAcquireFence and setDesiredTime could happen in between the splited setLayerName and setPostTime, where setLayerName inserts an entry but setPostTime actually initializes the structure and waitData position. This change combine setLayerName and setPostTime again to eliminate the hazard. Test: build Bug: b/118770127 Change-Id: Ia1961cb688bbabf23d88305750e69c9fa41da8dd --- services/surfaceflinger/BufferStateLayer.cpp | 3 +-- services/surfaceflinger/Layer.cpp | 5 ++--- services/surfaceflinger/TimeStats/TimeStats.cpp | 15 ++++----------- services/surfaceflinger/TimeStats/TimeStats.h | 4 ++-- 4 files changed, 9 insertions(+), 18 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 5df8ade34e..73098bf2aa 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -470,8 +470,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse } // TODO(marissaw): properly support mTimeStats - mTimeStats.setLayerName(layerID, getName().c_str()); - mTimeStats.setPostTime(layerID, getFrameNumber(), latchTime); + mTimeStats.setPostTime(layerID, getFrameNumber(), getName().c_str(), latchTime); mTimeStats.setAcquireFence(layerID, getFrameNumber(), getCurrentFenceTime()); mTimeStats.setLatchTime(layerID, getFrameNumber(), latchTime); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 88c3c8a018..2e564e7d94 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1476,9 +1476,8 @@ void Layer::onDisconnect() { void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, FrameEventHistoryDelta* outDelta) { if (newTimestamps) { - const int32_t layerID = getSequence(); - mTimeStats.setLayerName(layerID, getName().c_str()); - mTimeStats.setPostTime(layerID, newTimestamps->frameNumber, newTimestamps->postedTime); + mTimeStats.setPostTime(getSequence(), newTimestamps->frameNumber, getName().c_str(), + newTimestamps->postedTime); } Mutex::Autolock lock(mFrameEventHistoryMutex); diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp index c219afd85d..ace7c1b454 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.cpp +++ b/services/surfaceflinger/TimeStats/TimeStats.cpp @@ -241,25 +241,18 @@ static bool layerNameIsValid(const std::string& layerName) { return std::regex_match(layerName.begin(), layerName.end(), layerNameRegex); } -void TimeStats::setLayerName(int32_t layerID, const std::string& layerName) { +void TimeStats::setPostTime(int32_t layerID, uint64_t frameNumber, const std::string& layerName, + nsecs_t postTime) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%s]", layerID, layerName.c_str()); + ALOGV("[%d]-[%" PRIu64 "]-[%s]-PostTime[%" PRId64 "]", layerID, frameNumber, layerName.c_str(), + postTime); std::lock_guard lock(mMutex); if (!mTimeStatsTracker.count(layerID) && layerNameIsValid(layerName)) { mTimeStatsTracker[layerID].layerName = layerName; } -} - -void TimeStats::setPostTime(int32_t layerID, uint64_t frameNumber, nsecs_t postTime) { - if (!mEnabled.load()) return; - - ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-PostTime[%" PRId64 "]", layerID, frameNumber, postTime); - - std::lock_guard lock(mMutex); if (!mTimeStatsTracker.count(layerID)) return; LayerRecord& layerRecord = mTimeStatsTracker[layerID]; if (layerRecord.timeRecords.size() == MAX_NUM_TIME_RECORDS) { diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h index d1e554cbd2..184bf40967 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.h +++ b/services/surfaceflinger/TimeStats/TimeStats.h @@ -86,8 +86,8 @@ public: void incrementMissedFrames(); void incrementClientCompositionFrames(); - void setLayerName(int32_t layerID, const std::string& layerName); - void setPostTime(int32_t layerID, uint64_t frameNumber, nsecs_t postTime); + void setPostTime(int32_t layerID, uint64_t frameNumber, const std::string& layerName, + nsecs_t postTime); void setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latchTime); void setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t desiredTime); void setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t acquireTime); -- cgit v1.2.3-59-g8ed1b From 2e102c9d5e2333cd8fe984ed67739eefb3b08f19 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Tue, 23 Oct 2018 12:11:15 -0700 Subject: SurfaceFlinger: Share ownership of layers between State and Handle. Currently the only strong reference to a Layer is held by their parent or the containing layer stack. Firstly, it means that we can not create a SurfaceControl with a null parent. For example, a media decoding library may wish to offer an unparented SurfaceControl representing the decoding Surface, and allow the consumer to parent it between various SurfaceControls as they wish. Secondly it requires lifetime coordination between various levels of the hierarchy, when adding a child you have to be careful to observe the lifetime of the parent because your BufferQueue may become suddenly abandoned at any point. In this change we switch to a reference counted model, such that the Layer remains valid as long as there is a handle to it. We also end the behavior of passing on BufferQueue abandon to children. Layers are only abandoned/disposed when an explicit call to remove is made, or the last reference is dropped. In this CL we switch the handle to holding a strong pointer. We have the handle and the current state forward their references to the main thread to be dropped. We move the contents of onRemoved to the destructor to ensure they are dropped when the last reference is dropped. A second CL will replace the concept of "onRemovedFromCurrentState" with the concept of parent=null, and remove the explicit destroy method, replacing it with an IPC reparent to null. Two additional refactorings are required to follow the other changes. First since we moved mNumLayers to ~Layer it will be executed for the fake parent layer created during screenshots but mNumLayers++ (in addClientLayer) will not be incremented. The most straightforward solution is to balance mNumLayers from the c'tor/d'tor. Second since abandon() is virtual calling it from the d'tor is not safe. We move the call to BufferQueueLayer and remove the abstract method entirely. Bug: 62536731 Bug: 111373437 Bug: 111297488 Test: Transaction_test.cpp Change-Id: I3e815eb9cee39f6def1ef459811448698a93f5c8 --- services/surfaceflinger/BufferQueueLayer.cpp | 20 ++++-- services/surfaceflinger/BufferQueueLayer.h | 2 - services/surfaceflinger/Layer.cpp | 57 ++++++++++----- services/surfaceflinger/Layer.h | 18 ++--- services/surfaceflinger/SurfaceFlinger.cpp | 80 +++++++--------------- services/surfaceflinger/SurfaceFlinger.h | 7 +- services/surfaceflinger/tests/Transaction_test.cpp | 31 +++++++++ 7 files changed, 118 insertions(+), 97 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index e592a8bf98..c130bc5105 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -23,7 +23,9 @@ namespace android { BufferQueueLayer::BufferQueueLayer(const LayerCreationArgs& args) : BufferLayer(args) {} -BufferQueueLayer::~BufferQueueLayer() = default; +BufferQueueLayer::~BufferQueueLayer() { + mConsumer->abandon(); +} // ----------------------------------------------------------------------- // Interface implementation for Layer @@ -33,10 +35,6 @@ void BufferQueueLayer::onLayerDisplayed(const sp& releaseFence) { mConsumer->setReleaseFence(releaseFence); } -void BufferQueueLayer::abandon() { - mConsumer->abandon(); -} - void BufferQueueLayer::setTransformHint(uint32_t orientation) const { mConsumer->setTransformHint(orientation); } @@ -380,7 +378,17 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { mFlinger->mInterceptor->saveBufferUpdate(this, item.mGraphicBuffer->getWidth(), item.mGraphicBuffer->getHeight(), item.mFrameNumber); - mFlinger->signalLayerUpdate(); + + // If this layer is orphaned, then we run a fake vsync pulse so that + // dequeueBuffer doesn't block indefinitely. + if (isRemovedFromCurrentState()) { + bool ignored = false; + latchBuffer(ignored, systemTime(), Fence::NO_FENCE); + usleep(16000); + releasePendingBuffer(systemTime()); + } else { + mFlinger->signalLayerUpdate(); + } } void BufferQueueLayer::onFrameReplaced(const BufferItem& item) { diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index abe0bc7c0a..c9ebe042b8 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -40,8 +40,6 @@ public: public: void onLayerDisplayed(const sp& releaseFence) override; - void abandon() override; - void setTransformHint(uint32_t orientation) const override; std::vector getOccupancyHistory(bool forceFlush) override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 2e564e7d94..f29dfc0f1b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -111,6 +111,8 @@ Layer::Layer(const LayerCreationArgs& args) args.flinger->getCompositorTiming(&compositorTiming); mFrameEventHistory.initializeCompositorTiming(compositorTiming); mFrameTracker.setDisplayRefreshPeriod(compositorTiming.interval); + + mFlinger->onLayerCreated(); } Layer::~Layer() { @@ -119,13 +121,11 @@ Layer::~Layer() { c->detachLayer(this); } - for (auto& point : mRemoteSyncPoints) { - point->setTransactionApplied(); - } - for (auto& point : mLocalSyncPoints) { - point->setFrameAvailable(); - } mFrameTracker.logAndResetStats(mName); + + destroyAllHwcLayers(); + + mFlinger->onLayerDestroyed(); } // --------------------------------------------------------------------------- @@ -140,10 +140,9 @@ Layer::~Layer() { void Layer::onLayerDisplayed(const sp& /*releaseFence*/) {} void Layer::onRemovedFromCurrentState() { - // the layer is removed from SF mCurrentState to mLayersPendingRemoval - - mPendingRemoval = true; + mRemovedFromCurrentState = true; + // the layer is removed from SF mCurrentState to mLayersPendingRemoval if (mCurrentState.zOrderRelativeOf != nullptr) { sp strongRelative = mCurrentState.zOrderRelativeOf.promote(); if (strongRelative != nullptr) { @@ -153,19 +152,26 @@ void Layer::onRemovedFromCurrentState() { mCurrentState.zOrderRelativeOf = nullptr; } - for (const auto& child : mCurrentChildren) { - child->onRemovedFromCurrentState(); + // Since we are no longer reachable from CurrentState SurfaceFlinger + // will no longer invoke doTransaction for us, and so we will + // never finish applying transactions. We signal the sync point + // now so that another layer will not become indefinitely + // blocked. + for (auto& point: mRemoteSyncPoints) { + point->setTransactionApplied(); } -} + mRemoteSyncPoints.clear(); -void Layer::onRemoved() { - // the layer is removed from SF mLayersPendingRemoval - abandon(); - - destroyAllHwcLayers(); + { + Mutex::Autolock syncLock(mLocalSyncPointMutex); + for (auto& point : mLocalSyncPoints) { + point->setFrameAvailable(); + } + mLocalSyncPoints.clear(); + } for (const auto& child : mCurrentChildren) { - child->onRemoved(); + child->onRemovedFromCurrentState(); } } @@ -228,6 +234,10 @@ void Layer::destroyAllHwcLayers() { } LOG_ALWAYS_FATAL_IF(!getBE().mHwcLayers.empty(), "All hardware composer layers should have been destroyed"); + + for (const sp& child : mDrawingChildren) { + child->destroyAllHwcLayers(); + } } Rect Layer::getContentCrop() const { @@ -752,6 +762,9 @@ bool Layer::addSyncPoint(const std::shared_ptr& point) { // relevant frame return false; } + if (isRemovedFromCurrentState()) { + return false; + } Mutex::Autolock lock(mLocalSyncPointMutex); mLocalSyncPoints.push_back(point); @@ -825,7 +838,9 @@ void Layer::pushPendingState() { // If this transaction is waiting on the receipt of a frame, generate a sync // point and send it to the remote layer. - if (mCurrentState.barrierLayer_legacy != nullptr) { + // We don't allow installing sync points after we are removed from the current state + // as we won't be able to signal our end. + if (mCurrentState.barrierLayer_legacy != nullptr && !isRemovedFromCurrentState()) { sp barrierLayer = mCurrentState.barrierLayer_legacy.promote(); if (barrierLayer == nullptr) { ALOGE("[%s] Unable to promote barrier Layer.", mName.string()); @@ -1994,6 +2009,10 @@ void Layer::writeToProto(LayerProto* layerInfo, int32_t displayId) { } } +bool Layer::isRemovedFromCurrentState() const { + return mRemovedFromCurrentState; +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 5d05f0530b..12671ff51d 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -346,7 +346,7 @@ public: virtual bool isCreatedFromMainThread() const { return false; } - bool isPendingRemoval() const { return mPendingRemoval; } + bool isRemovedFromCurrentState() const; void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing); @@ -394,8 +394,6 @@ public: */ virtual void onLayerDisplayed(const sp& releaseFence); - virtual void abandon() {} - virtual bool shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { return false; } virtual void setTransformHint(uint32_t /*orientation*/) const { } @@ -475,12 +473,6 @@ public: */ void onRemovedFromCurrentState(); - /* - * called with the state lock from the main thread when the layer is - * removed from the pending removal list - */ - void onRemoved(); - // Updates the transform hint in our SurfaceFlingerConsumer to match // the current orientation of the display device. void updateTransformHint(const sp& display) const; @@ -595,12 +587,12 @@ protected: */ class LayerCleaner { sp mFlinger; - wp mLayer; + sp mLayer; protected: ~LayerCleaner() { // destroy client resources - mFlinger->onLayerDestroyed(mLayer); + mFlinger->onHandleDestroyed(mLayer); } public: @@ -702,6 +694,8 @@ public: virtual PixelFormat getPixelFormat() const { return PIXEL_FORMAT_NONE; } bool getPremultipledAlpha() const; + bool mPendingHWCDestroy{false}; + protected: // ----------------------------------------------------------------------- bool usingRelativeZ(LayerVector::StateSet stateSet); @@ -745,7 +739,7 @@ protected: // Whether filtering is needed b/c of the drawingstate bool mNeedsFiltering{false}; - bool mPendingRemoval{false}; + std::atomic mRemovedFromCurrentState{false}; // page-flip thread (currently main thread) bool mProtectedByApp{false}; // application requires protected path to external sink diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5c31ada5ef..f8ad156254 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2735,7 +2735,15 @@ void SurfaceFlinger::commitTransaction() for (const auto& l : mLayersPendingRemoval) { recordBufferingStats(l->getName().string(), l->getOccupancyHistory(true)); - l->onRemoved(); + + // We need to release the HWC layers when the Layer is removed + // from the current state otherwise the HWC layer just continues + // showing at its last configured state until we eventually + // abandon the buffer queue. + if (l->isRemovedFromCurrentState()) { + l->destroyAllHwcLayers(); + l->releasePendingBuffer(systemTime()); + } } mLayersPendingRemoval.clear(); } @@ -3168,7 +3176,7 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, if (parent == nullptr) { mCurrentState.layersSortedByZ.add(lbc); } else { - if (parent->isPendingRemoval()) { + if (parent->isRemovedFromCurrentState()) { ALOGE("addClientLayer called with a removed parent"); return NAME_NOT_FOUND; } @@ -3184,7 +3192,6 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, mMaxGraphicBufferProducerListSize, mNumLayers); } mLayersAdded = true; - mNumLayers++; } // attach this layer to the client @@ -3198,52 +3205,22 @@ status_t SurfaceFlinger::removeLayer(const sp& layer, bool topLevelOnly) return removeLayerLocked(mStateLock, layer, topLevelOnly); } -status_t SurfaceFlinger::removeLayerLocked(const Mutex&, const sp& layer, +status_t SurfaceFlinger::removeLayerLocked(const Mutex& lock, const sp& layer, bool topLevelOnly) { - if (layer->isPendingRemoval()) { - return NO_ERROR; - } - const auto& p = layer->getParent(); ssize_t index; if (p != nullptr) { if (topLevelOnly) { return NO_ERROR; } - - sp ancestor = p; - while (ancestor->getParent() != nullptr) { - ancestor = ancestor->getParent(); - } - if (mCurrentState.layersSortedByZ.indexOf(ancestor) < 0) { - ALOGE("removeLayer called with a layer whose parent has been removed"); - return NAME_NOT_FOUND; - } - index = p->removeChild(layer); } else { index = mCurrentState.layersSortedByZ.remove(layer); } - // As a matter of normal operation, the LayerCleaner will produce a second - // attempt to remove the surface. The Layer will be kept alive in mDrawingState - // so we will succeed in promoting it, but it's already been removed - // from mCurrentState. As long as we can find it in mDrawingState we have no problem - // otherwise something has gone wrong and we are leaking the layer. - if (index < 0 && mDrawingState.layersSortedByZ.indexOf(layer) < 0) { - ALOGE("Failed to find layer (%s) in layer parent (%s).", - layer->getName().string(), - (p != nullptr) ? p->getName().string() : "no-parent"); - return BAD_VALUE; - } else if (index < 0) { - return NO_ERROR; - } - layer->onRemovedFromCurrentState(); - mLayersPendingRemoval.add(layer); - mLayersRemoved = true; - mNumLayers -= 1 + layer->getChildrenCount(); - setTransactionFlags(eTransactionNeeded); + + markLayerPendingRemovalLocked(lock, layer); return NO_ERROR; } @@ -3444,11 +3421,6 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState return 0; } - if (layer->isPendingRemoval()) { - ALOGW("Attempting to set client state on removed layer: %s", layer->getName().string()); - return 0; - } - uint32_t flags = 0; const uint32_t what = s.what; @@ -3652,11 +3624,6 @@ void SurfaceFlinger::setDestroyStateLocked(const ComposerState& composerState) { return; } - if (layer->isPendingRemoval()) { - ALOGW("Attempting to destroy on removed layer: %s", layer->getName().string()); - return; - } - if (state.what & layer_state_t::eDestroySurface) { removeLayerLocked(mStateLock, layer); } @@ -3830,17 +3797,16 @@ status_t SurfaceFlinger::onLayerRemoved(const sp& client, const sp& layer) +void SurfaceFlinger::markLayerPendingRemovalLocked(const Mutex&, const sp& layer) { + mLayersPendingRemoval.add(layer); + mLayersRemoved = true; + setTransactionFlags(eTransactionNeeded); +} + +void SurfaceFlinger::onHandleDestroyed(const sp& layer) { - // called by ~LayerCleaner() when all references to the IBinder (handle) - // are gone - sp l = layer.promote(); - if (l == nullptr) { - // The layer has already been removed, carry on - return NO_ERROR; - } - // If we have a parent, then we can continue to live as long as it does. - return removeLayer(l, true); + Mutex::Autolock lock(mStateLock); + markLayerPendingRemovalLocked(mStateLock, layer); } // --------------------------------------------------------------------------- @@ -5189,7 +5155,7 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, auto layerHandle = reinterpret_cast(layerHandleBinder.get()); auto parent = layerHandle->owner.promote(); - if (parent == nullptr || parent->isPendingRemoval()) { + if (parent == nullptr || parent->isRemovedFromCurrentState()) { ALOGE("captureLayers called with a removed parent"); return NAME_NOT_FOUND; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index d60765cc1a..87ce996836 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -364,6 +364,9 @@ public: bool authenticateSurfaceTextureLocked( const sp& bufferProducer) const; + inline void onLayerCreated() { mNumLayers++; } + inline void onLayerDestroyed() { mNumLayers--; } + private: friend class Client; friend class DisplayEventConnection; @@ -575,10 +578,12 @@ private: // ISurfaceComposerClient::destroySurface() status_t onLayerRemoved(const sp& client, const sp& handle); + void markLayerPendingRemovalLocked(const Mutex& /* mStateLock */, const sp& layer); + // called when all clients have released all their references to // this layer meaning it is entirely safe to destroy all // resources associated to this layer. - status_t onLayerDestroyed(const wp& layer); + void onHandleDestroyed(const sp& layer); // remove a layer from SurfaceFlinger immediately status_t removeLayer(const sp& layer, bool topLevelOnly = false); diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index c814142f49..57a2227593 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -2614,6 +2614,37 @@ TEST_F(ChildLayerTest, ReparentChildren) { } } +TEST_F(ChildLayerTest, ChildrenSurviveParentDestruction) { + sp mGrandChild = + mClient->createSurface(String8("Grand Child"), 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mChild.get()); + fillSurfaceRGBA8(mGrandChild, 111, 111, 111); + + { + SCOPED_TRACE("Grandchild visible"); + ScreenCapture::captureScreen(&mCapture); + mCapture->checkPixel(64, 64, 111, 111, 111); + } + + mChild->clear(); + + { + SCOPED_TRACE("After destroying child"); + ScreenCapture::captureScreen(&mCapture); + mCapture->expectFGColor(64, 64); + } + + asTransaction([&](Transaction& t) { + t.reparent(mGrandChild, mFGSurfaceControl->getHandle()); + }); + + { + SCOPED_TRACE("After reparenting grandchild"); + ScreenCapture::captureScreen(&mCapture); + mCapture->checkPixel(64, 64, 111, 111, 111); + } +} + TEST_F(ChildLayerTest, DetachChildrenSameClient) { asTransaction([&](Transaction& t) { t.show(mChild); -- cgit v1.2.3-59-g8ed1b From 075d317063d815430d3a45acc7292e0681f73ee5 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Thu, 24 May 2018 15:50:06 -0700 Subject: SF: Generalize display management This CL enables SF to manage an arbitrary number of physical displays. Previously, displays were identified by 32-bit IDs, where 0 is the internal display, 1 is the external display, [2, INT32_MAX] are HWC virtual displays, and -1 represents an invalid display or a non-HWC virtual display. If the HWC provides display identification data, SF now allocates 64-bit display IDs for physical and HWC virtual displays. The IDs are expressed using an option type, where the null value represents an invalid display or non-HWC virtual display. Without HWC support, SF falls back to legacy behavior with at most two physical displays. The dynamic display IDs are translated to the legacy constants at the SF/DMS boundary, as a stopgap until the framework is generalized. Bug: 74619554 Test: Connect 3 displays and create virtual displays on HWC 2.2 and 2.3 Test: libsurfaceflinger_unittest Test: SurfaceFlinger_test Change-Id: I0a4a57b6ab7de2dbcf719a4eb1a19a133694012e --- cmds/surfacereplayer/proto/src/trace.proto | 2 +- .../replayer/trace_creator/trace_creator.py | 2 +- services/surfaceflinger/BufferLayer.cpp | 26 +- services/surfaceflinger/BufferLayer.h | 8 +- services/surfaceflinger/BufferQueueLayer.cpp | 3 +- services/surfaceflinger/BufferQueueLayer.h | 3 +- services/surfaceflinger/BufferStateLayer.cpp | 3 +- services/surfaceflinger/BufferStateLayer.h | 4 +- services/surfaceflinger/ColorLayer.cpp | 11 +- services/surfaceflinger/ColorLayer.h | 3 +- services/surfaceflinger/ContainerLayer.cpp | 2 +- services/surfaceflinger/ContainerLayer.h | 3 +- services/surfaceflinger/DisplayDevice.cpp | 33 +- services/surfaceflinger/DisplayDevice.h | 53 +- .../DisplayHardware/DisplayIdentification.cpp | 17 +- .../DisplayHardware/DisplayIdentification.h | 12 +- .../DisplayHardware/FramebufferSurface.cpp | 32 +- .../DisplayHardware/FramebufferSurface.h | 7 +- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 331 +++++++------ .../surfaceflinger/DisplayHardware/HWComposer.h | 118 ++--- .../DisplayHardware/VirtualDisplaySurface.cpp | 95 ++-- .../DisplayHardware/VirtualDisplaySurface.h | 13 +- services/surfaceflinger/Layer.cpp | 51 +- services/surfaceflinger/Layer.h | 39 +- services/surfaceflinger/LayerBE.h | 8 +- services/surfaceflinger/SurfaceFlinger.cpp | 540 ++++++++++----------- services/surfaceflinger/SurfaceFlinger.h | 49 +- services/surfaceflinger/SurfaceInterceptor.cpp | 4 +- .../tests/unittests/CompositionTest.cpp | 18 +- .../tests/unittests/DisplayIdentificationTest.cpp | 64 ++- .../tests/unittests/DisplayIdentificationTest.h | 27 ++ .../tests/unittests/DisplayTransactionTest.cpp | 310 ++++++++---- .../tests/unittests/TestableSurfaceFlinger.h | 59 ++- 33 files changed, 1101 insertions(+), 849 deletions(-) create mode 100644 services/surfaceflinger/tests/unittests/DisplayIdentificationTest.h (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto index 68ddeb02d6..c169b763d4 100644 --- a/cmds/surfacereplayer/proto/src/trace.proto +++ b/cmds/surfacereplayer/proto/src/trace.proto @@ -160,7 +160,7 @@ message VSyncEvent { message DisplayCreation { required int32 id = 1; required string name = 2; - required int32 type = 3; + optional uint64 display_id = 3; required bool is_secure = 4; } diff --git a/cmds/surfacereplayer/replayer/trace_creator/trace_creator.py b/cmds/surfacereplayer/replayer/trace_creator/trace_creator.py index a892e46816..d63d97f6b4 100644 --- a/cmds/surfacereplayer/replayer/trace_creator/trace_creator.py +++ b/cmds/surfacereplayer/replayer/trace_creator/trace_creator.py @@ -172,7 +172,7 @@ def surface_delete(increment): def display_create(increment): increment.display_creation.id = int(input("Enter id: ")) increment.display_creation.name = str(raw_input("Enter name: ")) - increment.display_creation.type = int(input("Enter type: ")) + increment.display_creation.display_id = int(input("Enter display ID: ")) increment.display_creation.is_secure = bool(input("Enter if secure: ")) def display_delete(increment): diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 440f1e24e1..641bd8d1c3 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -229,15 +229,14 @@ bool BufferLayer::isHdrY410() const { getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102); } -void BufferLayer::setPerFrameData(const sp& display) { +void BufferLayer::setPerFrameData(DisplayId displayId, const ui::Transform& transform, + const Rect& viewport, int32_t supportedPerFrameMetadata) { // Apply this display's projection's viewport to the visible region // before giving it to the HWC HAL. - const ui::Transform& tr = display->getTransform(); - const auto& viewport = display->getViewport(); - Region visible = tr.transform(visibleRegion.intersect(viewport)); - const auto displayId = display->getId(); + Region visible = transform.transform(visibleRegion.intersect(viewport)); + if (!hasHwcLayer(displayId)) { - ALOGE("[%s] failed to setPerFrameData: no HWC layer found (%d)", + ALOGE("[%s] failed to setPerFrameData: no HWC layer found for display %" PRIu64, mName.string(), displayId); return; } @@ -290,7 +289,7 @@ void BufferLayer::setPerFrameData(const sp& display) { } const HdrMetadata& metadata = getDrawingHdrMetadata(); - error = hwcLayer->setPerFrameMetadata(display->getSupportedPerFrameMetadata(), metadata); + error = hwcLayer->setPerFrameMetadata(supportedPerFrameMetadata, metadata); if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) { ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), to_string(error).c_str(), static_cast(error)); @@ -303,10 +302,10 @@ void BufferLayer::setPerFrameData(const sp& display) { } getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace; getBE().compositionInfo.hwc.hdrMetadata = getDrawingHdrMetadata(); - getBE().compositionInfo.hwc.supportedPerFrameMetadata = display->getSupportedPerFrameMetadata(); + getBE().compositionInfo.hwc.supportedPerFrameMetadata = supportedPerFrameMetadata; getBE().compositionInfo.hwc.colorTransform = getColorTransform(); - setHwcLayerBuffer(display); + setHwcLayerBuffer(displayId); } bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { @@ -318,10 +317,10 @@ bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { return hasReadyFrame(); } -bool BufferLayer::onPostComposition(const std::shared_ptr& glDoneFence, +bool BufferLayer::onPostComposition(const std::optional& displayId, + const std::shared_ptr& glDoneFence, const std::shared_ptr& presentFence, const CompositorTiming& compositorTiming) { - // mFrameLatencyNeeded is true when a new frame was latched for the // composition. if (!mFrameLatencyNeeded) return false; @@ -352,11 +351,10 @@ bool BufferLayer::onPostComposition(const std::shared_ptr& glDoneFenc if (presentFence->isValid()) { mTimeStats.setPresentFence(layerID, mCurrentFrameNumber, presentFence); mFrameTracker.setActualPresentFence(std::shared_ptr(presentFence)); - } else if (mFlinger->getHwComposer().isConnected(HWC_DISPLAY_PRIMARY)) { + } else if (displayId && mFlinger->getHwComposer().isConnected(*displayId)) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. - const nsecs_t actualPresentTime = - mFlinger->getHwComposer().getRefreshTimestamp(HWC_DISPLAY_PRIMARY); + const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(*displayId); mTimeStats.setPresentTime(layerID, mCurrentFrameNumber, actualPresentTime); mFrameTracker.setActualPresentTime(actualPresentTime); } diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index d000d85a2d..b3ea7e6bf8 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -80,10 +80,12 @@ public: bool isHdrY410() const override; - void setPerFrameData(const sp& displayDevice) override; + void setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport, + int32_t supportedPerFrameMetadata) override; bool onPreComposition(nsecs_t refreshStartTime) override; - bool onPostComposition(const std::shared_ptr& glDoneFence, + bool onPostComposition(const std::optional& displayId, + const std::shared_ptr& glDoneFence, const std::shared_ptr& presentFence, const CompositorTiming& compositorTiming) override; @@ -145,7 +147,7 @@ private: virtual status_t updateActiveBuffer() = 0; virtual status_t updateFrameNumber(nsecs_t latchTime) = 0; - virtual void setHwcLayerBuffer(const sp& display) = 0; + virtual void setHwcLayerBuffer(DisplayId displayId) = 0; // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index c130bc5105..e10548f06e 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -325,8 +325,7 @@ status_t BufferQueueLayer::updateFrameNumber(nsecs_t latchTime) { return NO_ERROR; } -void BufferQueueLayer::setHwcLayerBuffer(const sp& display) { - const auto displayId = display->getId(); +void BufferQueueLayer::setHwcLayerBuffer(DisplayId displayId) { auto& hwcInfo = getBE().mHwcLayers[displayId]; auto& hwcLayer = hwcInfo.layer; diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index c9ebe042b8..74dd21e0d0 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -94,8 +94,7 @@ private: status_t updateActiveBuffer() override; status_t updateFrameNumber(nsecs_t latchTime) override; - void setHwcLayerBuffer(const sp& display) override; - // ----------------------------------------------------------------------- + void setHwcLayerBuffer(DisplayId displayId) override; // ----------------------------------------------------------------------- // Interface implementation for BufferLayerConsumer::ContentsChangedListener diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 73098bf2aa..8d5984157a 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -497,8 +497,7 @@ status_t BufferStateLayer::updateFrameNumber(nsecs_t /*latchTime*/) { return NO_ERROR; } -void BufferStateLayer::setHwcLayerBuffer(const sp& display) { - const auto displayId = display->getId(); +void BufferStateLayer::setHwcLayerBuffer(DisplayId displayId) { auto& hwcInfo = getBE().mHwcLayers[displayId]; auto& hwcLayer = hwcInfo.layer; diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 0c6eaf5a3b..381cd28f40 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -121,8 +121,8 @@ private: status_t updateActiveBuffer() override; status_t updateFrameNumber(nsecs_t latchTime) override; - void setHwcLayerBuffer(const sp& display) override; - // ----------------------------------------------------------------------- + void setHwcLayerBuffer(DisplayId displayId) override; + private: void onFirstRef() override; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 263f872826..ad716efa32 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -57,13 +57,12 @@ bool ColorLayer::isVisible() const { return !isHiddenByPolicy() && getAlpha() > 0.0f; } -void ColorLayer::setPerFrameData(const sp& display) { - const ui::Transform& tr = display->getTransform(); - const auto& viewport = display->getViewport(); - Region visible = tr.transform(visibleRegion.intersect(viewport)); - const auto displayId = display->getId(); +void ColorLayer::setPerFrameData(DisplayId displayId, const ui::Transform& transform, + const Rect& viewport, int32_t /* supportedPerFrameMetadata */) { + Region visible = transform.transform(visibleRegion.intersect(viewport)); + if (!hasHwcLayer(displayId)) { - ALOGE("[%s] failed to setPerFrameData: no HWC layer found (%d)", + ALOGE("[%s] failed to setPerFrameData: no HWC layer found for display %" PRIu64, mName.string(), displayId); return; } diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index 2febe9a5b0..d1b1697af8 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -33,7 +33,8 @@ public: bool useIdentityTransform); bool isVisible() const override; - void setPerFrameData(const sp& display) override; + void setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport, + int32_t supportedPerFrameMetadata) override; bool onPreComposition(nsecs_t /*refreshStartTime*/) override { return false; } diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index 44e843e241..ca49f6c7af 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -32,6 +32,6 @@ bool ContainerLayer::isVisible() const { return !isHiddenByPolicy(); } -void ContainerLayer::setPerFrameData(const sp&) {} +void ContainerLayer::setPerFrameData(DisplayId, const ui::Transform&, const Rect&, int32_t) {} } // namespace android diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index 316db83ab2..413844b6f5 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -33,7 +33,8 @@ public: bool useIdentityTransform) override; bool isVisible() const override; - void setPerFrameData(const sp& display) override; + void setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport, + int32_t supportedPerFrameMetadata) override; bool isCreatedFromMainThread() const override { return true; } diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 91b18c9fd7..7c5c1bc8c3 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -212,15 +212,14 @@ RenderIntent getHwcRenderIntent(const std::vector& hwcIntents, Ren DisplayDeviceCreationArgs::DisplayDeviceCreationArgs(const sp& flinger, const wp& displayToken, - DisplayDevice::DisplayType type, int32_t id) - : flinger(flinger), displayToken(displayToken), type(type), id(id) {} + const std::optional& displayId) + : flinger(flinger), displayToken(displayToken), displayId(displayId) {} DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) : lastCompositionHadVisibleLayers(false), mFlinger(args.flinger), - mType(args.type), - mId(args.id), mDisplayToken(args.displayToken), + mId(args.displayId), mNativeWindow(args.nativeWindow), mDisplaySurface(args.displaySurface), mSurface{std::move(args.renderSurface)}, @@ -228,6 +227,7 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) mDisplayHeight(args.displayHeight), mDisplayInstallOrientation(args.displayInstallOrientation), mPageFlipCount(0), + mIsVirtual(args.isVirtual), mIsSecure(args.isSecure), mLayerStack(NO_LAYER_STACK), mOrientation(), @@ -240,7 +240,8 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) mHasHdr10(false), mHasHLG(false), mHasDolbyVision(false), - mSupportedPerFrameMetadata(args.supportedPerFrameMetadata) { + mSupportedPerFrameMetadata(args.supportedPerFrameMetadata), + mIsPrimary(args.isPrimary) { populateColorModes(args.hwcColorModes); ALOGE_IF(!mNativeWindow, "No native window was set for display"); @@ -293,16 +294,12 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) DisplayDevice::~DisplayDevice() = default; void DisplayDevice::disconnect(HWComposer& hwc) { - if (mId >= 0) { - hwc.disconnectDisplay(mId); - mId = -1; + if (mId) { + hwc.disconnectDisplay(*mId); + mId.reset(); } } -bool DisplayDevice::isValid() const { - return mFlinger != nullptr; -} - int DisplayDevice::getWidth() const { return mDisplayWidth; } @@ -334,9 +331,11 @@ status_t DisplayDevice::beginFrame(bool mustRecompose) const { status_t DisplayDevice::prepareFrame(HWComposer& hwc, std::vector& compositionData) { - status_t error = hwc.prepare(*this, compositionData); - if (error != NO_ERROR) { - return error; + if (mId) { + status_t error = hwc.prepare(*mId, compositionData); + if (error != NO_ERROR) { + return error; + } } DisplaySurface::CompositionType compositionType; @@ -600,7 +599,7 @@ void DisplayDevice::setProjection(int orientation, // need to take care of primary display rotation for mGlobalTransform // for case if the panel is not installed aligned with device orientation - if (mType == DisplayType::DISPLAY_PRIMARY) { + if (isPrimary()) { DisplayDevice::orientationToTransfrom( (orientation + mDisplayInstallOrientation) % (DisplayState::eOrientation270 + 1), w, h, &R); @@ -648,7 +647,7 @@ uint32_t DisplayDevice::getPrimaryDisplayOrientationTransform() { } std::string DisplayDevice::getDebugName() const { - const auto id = mId >= 0 ? base::StringPrintf("%d, ", mId) : std::string(); + const auto id = mId ? base::StringPrintf("%" PRIu64 ", ", *mId) : std::string(); return base::StringPrintf("DisplayDevice{%s%s%s\"%s\"}", id.c_str(), isPrimary() ? "primary, " : "", isVirtual() ? "virtual, " : "", mDisplayName.c_str()); diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 152d0eca51..9ec7666ea6 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -37,6 +38,7 @@ #include #include +#include "DisplayHardware/DisplayIdentification.h" #include "RenderArea.h" struct ANativeWindow; @@ -66,25 +68,15 @@ public: Region undefinedRegion; bool lastCompositionHadVisibleLayers; - enum DisplayType { - DISPLAY_ID_INVALID = -1, - DISPLAY_PRIMARY = HWC_DISPLAY_PRIMARY, - DISPLAY_EXTERNAL = HWC_DISPLAY_EXTERNAL, - DISPLAY_VIRTUAL = HWC_DISPLAY_VIRTUAL, - NUM_BUILTIN_DISPLAY_TYPES = HWC_NUM_PHYSICAL_DISPLAY_TYPES, - }; - enum { NO_LAYER_STACK = 0xFFFFFFFF, }; explicit DisplayDevice(DisplayDeviceCreationArgs&& args); - ~DisplayDevice(); - // whether this is a valid object. An invalid DisplayDevice is returned - // when an non existing id is requested - bool isValid() const; + bool isVirtual() const { return mIsVirtual; } + bool isPrimary() const { return mIsPrimary; } // isSecure indicates whether this display can be trusted to display // secure surfaces. @@ -118,11 +110,9 @@ public: bool needsFiltering() const { return mNeedsFiltering; } uint32_t getLayerStack() const { return mLayerStack; } - int32_t getDisplayType() const { return mType; } - bool isPrimary() const { return mType == DISPLAY_PRIMARY; } - bool isVirtual() const { return mType == DISPLAY_VIRTUAL; } - int32_t getId() const { return mId; } - const wp& getDisplayToken() const { return mDisplayToken; } + + const std::optional& getId() const { return mId; } + const wp& getDisplayToken() const { return mDisplayToken; } int32_t getSupportedPerFrameMetadata() const { return mSupportedPerFrameMetadata; } @@ -207,13 +197,10 @@ public: void dump(String8& result) const; private: - /* - * Constants, set during initialization - */ - sp mFlinger; - DisplayType mType; - int32_t mId; - wp mDisplayToken; + const sp mFlinger; + const wp mDisplayToken; + + std::optional mId; // ANativeWindow this display is rendering into sp mNativeWindow; @@ -225,7 +212,9 @@ private: const int mDisplayInstallOrientation; mutable uint32_t mPageFlipCount; std::string mDisplayName; - bool mIsSecure; + + const bool mIsVirtual; + const bool mIsSecure; /* * Can only accessed from the main thread, these members @@ -299,13 +288,16 @@ private: const ui::ColorMode mode, const ui::RenderIntent intent); std::unordered_map mColorModes; + + // TODO(b/74619554): Remove special cases for primary display. + const bool mIsPrimary; }; struct DisplayDeviceState { - bool isVirtual() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; } + bool isVirtual() const { return !displayId.has_value(); } int32_t sequenceId = sNextSequenceId++; - DisplayDevice::DisplayType type = DisplayDevice::DISPLAY_ID_INVALID; + std::optional displayId; sp surface; uint32_t layerStack = DisplayDevice::NO_LAYER_STACK; Rect viewport; @@ -324,13 +316,13 @@ struct DisplayDeviceCreationArgs { // We use a constructor to ensure some of the values are set, without // assuming a default value. DisplayDeviceCreationArgs(const sp& flinger, const wp& displayToken, - DisplayDevice::DisplayType type, int32_t id); + const std::optional& displayId); const sp flinger; const wp displayToken; - const DisplayDevice::DisplayType type; - const int32_t id; + const std::optional displayId; + bool isVirtual{false}; bool isSecure{false}; sp nativeWindow; sp displaySurface; @@ -343,6 +335,7 @@ struct DisplayDeviceCreationArgs { int32_t supportedPerFrameMetadata{0}; std::unordered_map> hwcColorModes; int initialPowerMode{HWC_POWER_MODE_NORMAL}; + bool isPrimary{false}; }; class DisplayRenderArea : public RenderArea { diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp index dcc413863e..ec240f3009 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp +++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp @@ -33,6 +33,9 @@ using byte_view = std::basic_string_view; constexpr size_t kEdidHeaderLength = 5; +constexpr uint16_t kFallbackEdidManufacturerId = 0; +constexpr uint16_t kVirtualEdidManufacturerId = 0xffffu; + std::optional getEdidDescriptorType(const byte_view& view) { if (view.size() < kEdidHeaderLength || view[0] || view[1] || view[2] || view[4]) { return {}; @@ -165,7 +168,8 @@ std::optional getPnpId(uint16_t manufacturerId) { return a && b && c ? std::make_optional(PnpId{a, b, c}) : std::nullopt; } -std::optional generateDisplayId(uint8_t port, const DisplayIdentificationData& data) { +std::optional parseDisplayIdentificationData( + uint8_t port, const DisplayIdentificationData& data) { if (!isEdid(data)) { ALOGE("Display identification data has unknown format."); return {}; @@ -179,7 +183,16 @@ std::optional generateDisplayId(uint8_t port, const DisplayIdentifica // Hash display name instead of using product code or serial number, since the latter have been // observed to change on some displays with multiple inputs. const auto hash = static_cast(std::hash()(edid->displayName)); - return getEdidDisplayId(port, edid->manufacturerId, hash); + return DisplayIdentificationInfo{getEdidDisplayId(port, edid->manufacturerId, hash), + std::string(edid->displayName)}; +} + +DisplayId getFallbackDisplayId(uint8_t port) { + return getEdidDisplayId(port, kFallbackEdidManufacturerId, 0); +} + +DisplayId getVirtualDisplayId(uint32_t id) { + return getEdidDisplayId(0, kVirtualEdidManufacturerId, id); } } // namespace android diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h index 379f2d3be3..1f2e789d13 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h +++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -27,6 +28,11 @@ namespace android { using DisplayId = uint64_t; using DisplayIdentificationData = std::vector; +struct DisplayIdentificationInfo { + DisplayId id; + std::string name; +}; + // NUL-terminated plug and play ID. using PnpId = std::array; @@ -40,6 +46,10 @@ bool isEdid(const DisplayIdentificationData&); std::optional parseEdid(const DisplayIdentificationData&); std::optional getPnpId(uint16_t manufacturerId); -std::optional generateDisplayId(uint8_t port, const DisplayIdentificationData&); +std::optional parseDisplayIdentificationData( + uint8_t port, const DisplayIdentificationData&); + +DisplayId getFallbackDisplayId(uint8_t port); +DisplayId getVirtualDisplayId(uint32_t id); } // namespace android diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index e6d783434a..f3f8d9d859 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -52,26 +52,25 @@ using ui::Dataspace; * */ -FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp, - const sp& consumer) : - ConsumerBase(consumer), - mDisplayType(disp), - mCurrentBufferSlot(-1), - mCurrentBuffer(), - mCurrentFence(Fence::NO_FENCE), - mHwc(hwc), - mHasPendingRelease(false), - mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT), - mPreviousBuffer() -{ - ALOGV("Creating for display %d", disp); +FramebufferSurface::FramebufferSurface(HWComposer& hwc, DisplayId displayId, + const sp& consumer) + : ConsumerBase(consumer), + mDisplayId(displayId), + mCurrentBufferSlot(-1), + mCurrentBuffer(), + mCurrentFence(Fence::NO_FENCE), + mHwc(hwc), + mHasPendingRelease(false), + mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT), + mPreviousBuffer() { + ALOGV("Creating for display %" PRIu64, displayId); mName = "FramebufferSurface"; mConsumer->setConsumerName(mName); mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER); - const auto& activeConfig = mHwc.getActiveConfig(disp); + const auto& activeConfig = mHwc.getActiveConfig(displayId); mConsumer->setDefaultBufferSize(activeConfig->getWidth(), activeConfig->getHeight()); mConsumer->setMaxAcquiredBufferCount( @@ -142,8 +141,7 @@ status_t FramebufferSurface::nextBuffer(uint32_t& outSlot, mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer, &outSlot, &outBuffer); outDataspace = static_cast(item.mDataSpace); - status_t result = - mHwc.setClientTarget(mDisplayType, outSlot, outFence, outBuffer, outDataspace); + status_t result = mHwc.setClientTarget(mDisplayId, outSlot, outFence, outBuffer, outDataspace); if (result != NO_ERROR) { ALOGE("error posting framebuffer: %d", result); return result; @@ -161,7 +159,7 @@ void FramebufferSurface::freeBufferLocked(int slotIndex) { void FramebufferSurface::onFrameCommitted() { if (mHasPendingRelease) { - sp fence = mHwc.getPresentFence(mDisplayType); + sp fence = mHwc.getPresentFence(mDisplayId); if (fence->isValid()) { status_t result = addReleaseFence(mPreviousBufferSlot, mPreviousBuffer, fence); diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index 0fd8e9eaa4..2431dfd7c7 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -17,6 +17,7 @@ #ifndef ANDROID_SF_FRAMEBUFFER_SURFACE_H #define ANDROID_SF_FRAMEBUFFER_SURFACE_H +#include "DisplayIdentification.h" #include "DisplaySurface.h" #include "HWComposerBufferCache.h" @@ -38,7 +39,8 @@ class HWComposer; class FramebufferSurface : public ConsumerBase, public DisplaySurface { public: - FramebufferSurface(HWComposer& hwc, int disp, const sp& consumer); + FramebufferSurface(HWComposer& hwc, DisplayId displayId, + const sp& consumer); virtual status_t beginFrame(bool mustRecompose); virtual status_t prepareFrame(CompositionType compositionType); @@ -63,8 +65,7 @@ private: status_t nextBuffer(uint32_t& outSlot, sp& outBuffer, sp& outFence, ui::Dataspace& outDataspace); - // mDisplayType must match one of the HWC display types - int mDisplayType; + const DisplayId mDisplayId; // mCurrentBufferIndex is the slot index of the current buffer or // INVALID_BUFFER_SLOT to indicate that either there is no current buffer diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index b1daf12c6c..4c472b80ba 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -58,15 +58,15 @@ ALOGE("%s failed for HWC display %" PRIu64 ": %s", __FUNCTION__, hwcDisplayId, msg) #define LOG_DISPLAY_ERROR(displayId, msg) \ - ALOGE("%s failed for display %d: %s", __FUNCTION__, displayId, msg) + ALOGE("%s failed for display %" PRIu64 ": %s", __FUNCTION__, displayId, msg) -#define LOG_HWC_ERROR(what, error, displayId) \ - ALOGE("%s: %s failed for display %d: %s (%d)", __FUNCTION__, what, displayId, \ +#define LOG_HWC_ERROR(what, error, displayId) \ + ALOGE("%s: %s failed for display %" PRIu64 ": %s (%d)", __FUNCTION__, what, displayId, \ to_string(error).c_str(), static_cast(error)) #define RETURN_IF_INVALID_DISPLAY(displayId, ...) \ do { \ - if (!isValidDisplay(displayId)) { \ + if (mDisplayData.count(displayId) == 0) { \ LOG_DISPLAY_ERROR(displayId, "Invalid display"); \ return __VA_ARGS__; \ } \ @@ -118,11 +118,6 @@ bool HWComposer::hasCapability(HWC2::Capability capability) const return mHwcDevice->getCapabilities().count(capability) > 0; } -bool HWComposer::isValidDisplay(int32_t displayId) const { - return static_cast(displayId) < mDisplayData.size() && - mDisplayData[displayId].hwcDisplay; -} - void HWComposer::validateChange(HWC2::Composition from, HWC2::Composition to) { bool valid = true; switch (from) { @@ -148,52 +143,50 @@ void HWComposer::validateChange(HWC2::Composition from, HWC2::Composition to) { } } -std::optional HWComposer::onHotplug(hwc2_display_t hwcDisplayId, int32_t displayType, - HWC2::Connection connection) { - if (displayType >= HWC_NUM_PHYSICAL_DISPLAY_TYPES) { - ALOGE("Invalid display type of %d", displayType); - return {}; - } - - ALOGV("hotplug: %" PRIu64 ", %s %s", hwcDisplayId, - displayType == DisplayDevice::DISPLAY_PRIMARY ? "primary" : "external", - to_string(connection).c_str()); - mHwcDevice->onHotplug(hwcDisplayId, connection); - - std::optional displayId; +std::optional HWComposer::onHotplug(hwc2_display_t hwcDisplayId, + HWC2::Connection connection) { + std::optional info; - if (connection == HWC2::Connection::Connected) { - uint8_t port; - DisplayIdentificationData data; - if (getDisplayIdentificationData(hwcDisplayId, &port, &data)) { - displayId = generateDisplayId(port, data); - ALOGE_IF(!displayId, "Failed to generate stable ID for display %" PRIu64, hwcDisplayId); + if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) { + info = DisplayIdentificationInfo{*displayId, std::string()}; + } else { + if (connection == HWC2::Connection::Disconnected) { + ALOGE("Ignoring disconnection of invalid HWC display %" PRIu64, hwcDisplayId); + return {}; } + + info = onHotplugConnect(hwcDisplayId); + if (!info) return {}; } + ALOGV("%s: %s %s display %" PRIu64 " with HWC ID %" PRIu64, __FUNCTION__, + to_string(connection).c_str(), + hwcDisplayId == mInternalHwcDisplayId ? "internal" : "external", info->id, hwcDisplayId); + + mHwcDevice->onHotplug(hwcDisplayId, connection); + // Disconnect is handled through HWComposer::disconnectDisplay via // SurfaceFlinger's onHotplugReceived callback handling if (connection == HWC2::Connection::Connected) { - mDisplayData[displayType].hwcDisplay = mHwcDevice->getDisplayById(hwcDisplayId); - mHwcDisplaySlots[hwcDisplayId] = displayType; + mDisplayData[info->id].hwcDisplay = mHwcDevice->getDisplayById(hwcDisplayId); + mPhysicalDisplayIdMap[hwcDisplayId] = info->id; } - return displayId; + return info; } -bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp, int32_t* outDisplayId) { - const auto it = mHwcDisplaySlots.find(hwcDisplayId); - if (it == mHwcDisplaySlots.end()) { - LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid display"); +bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) { + const auto displayId = toPhysicalDisplayId(hwcDisplayId); + if (!displayId) { + LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display"); return false; } - const int32_t displayId = it->second; - RETURN_IF_INVALID_DISPLAY(displayId, false); + RETURN_IF_INVALID_DISPLAY(*displayId, false); - const auto& displayData = mDisplayData[displayId]; + const auto& displayData = mDisplayData[*displayId]; if (displayData.isVirtual) { - LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display"); + LOG_DISPLAY_ERROR(*displayId, "Invalid operation on virtual display"); return false; } @@ -204,31 +197,26 @@ bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp, int32_t // with the same timestamp when turning the display off and on. This // is a bug in the HWC implementation, but filter the extra events // out here so they don't cause havoc downstream. - if (timestamp == mLastHwVSync[displayId]) { - ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")", - timestamp); + if (timestamp == mLastHwVSync[*displayId]) { + ALOGW("Ignoring duplicate VSYNC event from HWC for display %" PRIu64 " (t=%" PRId64 ")", + *displayId, timestamp); return false; } - mLastHwVSync[displayId] = timestamp; - } - - if (outDisplayId) { - *outDisplayId = displayId; + mLastHwVSync[*displayId] = timestamp; } - char tag[16]; - snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", displayId); - ATRACE_INT(tag, ++mVSyncCounts[displayId] & 1); + const auto tag = "HW_VSYNC_" + std::to_string(*displayId); + ATRACE_INT(tag.c_str(), ++mVSyncCounts[*displayId] & 1); return true; } -status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height, - ui::PixelFormat* format, int32_t *outId) { +std::optional HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height, + ui::PixelFormat* format) { if (mRemainingHwcVirtualDisplays == 0) { ALOGE("%s: No remaining virtual displays", __FUNCTION__); - return NO_MEMORY; + return {}; } if (SurfaceFlinger::maxVirtualDisplaySize != 0 && @@ -236,41 +224,33 @@ status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height, height > SurfaceFlinger::maxVirtualDisplaySize)) { ALOGE("%s: Display size %ux%u exceeds maximum dimension of %" PRIu64, __FUNCTION__, width, height, SurfaceFlinger::maxVirtualDisplaySize); - return INVALID_OPERATION; + return {}; } - HWC2::Display* display; auto error = mHwcDevice->createVirtualDisplay(width, height, format, &display); if (error != HWC2::Error::None) { ALOGE("%s: Failed to create HWC virtual display", __FUNCTION__); - return NO_MEMORY; + return {}; } - size_t displaySlot = 0; - if (!mFreeDisplaySlots.empty()) { - displaySlot = *mFreeDisplaySlots.begin(); - mFreeDisplaySlots.erase(displaySlot); - } else if (mDisplayData.size() < INT32_MAX) { - // Don't bother allocating a slot larger than we can return - displaySlot = mDisplayData.size(); - mDisplayData.resize(displaySlot + 1); + DisplayId displayId; + if (mFreeVirtualDisplayIds.empty()) { + displayId = getVirtualDisplayId(mNextVirtualDisplayId++); } else { - ALOGE("%s: Unable to allocate a display slot", __FUNCTION__); - return NO_MEMORY; + displayId = *mFreeVirtualDisplayIds.begin(); + mFreeVirtualDisplayIds.erase(displayId); } - auto& displayData = mDisplayData[displaySlot]; + auto& displayData = mDisplayData[displayId]; displayData.hwcDisplay = display; displayData.isVirtual = true; --mRemainingHwcVirtualDisplays; - *outId = static_cast(displaySlot); - - return NO_ERROR; + return displayId; } -HWC2::Layer* HWComposer::createLayer(int32_t displayId) { +HWC2::Layer* HWComposer::createLayer(DisplayId displayId) { RETURN_IF_INVALID_DISPLAY(displayId, nullptr); auto display = mDisplayData[displayId].hwcDisplay; @@ -280,7 +260,7 @@ HWC2::Layer* HWComposer::createLayer(int32_t displayId) { return layer; } -void HWComposer::destroyLayer(int32_t displayId, HWC2::Layer* layer) { +void HWComposer::destroyLayer(DisplayId displayId, HWC2::Layer* layer) { RETURN_IF_INVALID_DISPLAY(displayId); auto display = mDisplayData[displayId].hwcDisplay; @@ -288,7 +268,8 @@ void HWComposer::destroyLayer(int32_t displayId, HWC2::Layer* layer) { RETURN_IF_HWC_ERROR(error, displayId); } -nsecs_t HWComposer::getRefreshTimestamp(int32_t displayId) const { +nsecs_t HWComposer::getRefreshTimestamp(DisplayId displayId) const { + RETURN_IF_INVALID_DISPLAY(displayId, 0); // this returns the last refresh timestamp. // if the last one is not available, we estimate it based on // the refresh period and whatever closest timestamp we have. @@ -298,17 +279,17 @@ nsecs_t HWComposer::getRefreshTimestamp(int32_t displayId) const { return now - ((now - mLastHwVSync[displayId]) % vsyncPeriod); } -bool HWComposer::isConnected(int32_t displayId) const { +bool HWComposer::isConnected(DisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, false); - return mDisplayData[displayId].hwcDisplay->isConnected(); + return mDisplayData.at(displayId).hwcDisplay->isConnected(); } -std::vector> - HWComposer::getConfigs(int32_t displayId) const { +std::vector> HWComposer::getConfigs( + DisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, {}); - auto& displayData = mDisplayData[displayId]; - auto configs = mDisplayData[displayId].hwcDisplay->getConfigs(); + const auto& displayData = mDisplayData.at(displayId); + auto configs = displayData.hwcDisplay->getConfigs(); if (displayData.configMap.empty()) { for (size_t i = 0; i < configs.size(); ++i) { displayData.configMap[i] = configs[i]; @@ -317,12 +298,12 @@ std::vector> return configs; } -std::shared_ptr - HWComposer::getActiveConfig(int32_t displayId) const { +std::shared_ptr HWComposer::getActiveConfig( + DisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, nullptr); std::shared_ptr config; - auto error = mDisplayData[displayId].hwcDisplay->getActiveConfig(&config); + auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfig(&config); if (error == HWC2::Error::BadConfig) { LOG_DISPLAY_ERROR(displayId, "No active config"); return nullptr; @@ -338,11 +319,11 @@ std::shared_ptr return config; } -int HWComposer::getActiveConfigIndex(int32_t displayId) const { +int HWComposer::getActiveConfigIndex(DisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, -1); int index; - auto error = mDisplayData[displayId].hwcDisplay->getActiveConfigIndex(&index); + auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfigIndex(&index); if (error == HWC2::Error::BadConfig) { LOG_DISPLAY_ERROR(displayId, "No active config"); return -1; @@ -358,17 +339,17 @@ int HWComposer::getActiveConfigIndex(int32_t displayId) const { return index; } -std::vector HWComposer::getColorModes(int32_t displayId) const { +std::vector HWComposer::getColorModes(DisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, {}); std::vector modes; - auto error = mDisplayData[displayId].hwcDisplay->getColorModes(&modes); + auto error = mDisplayData.at(displayId).hwcDisplay->getColorModes(&modes); RETURN_IF_HWC_ERROR(error, displayId, {}); return modes; } -status_t HWComposer::setActiveColorMode(int32_t displayId, ui::ColorMode mode, - ui::RenderIntent renderIntent) { +status_t HWComposer::setActiveColorMode(DisplayId displayId, ui::ColorMode mode, + ui::RenderIntent renderIntent) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); auto& displayData = mDisplayData[displayId]; @@ -381,8 +362,7 @@ status_t HWComposer::setActiveColorMode(int32_t displayId, ui::ColorMode mode, return NO_ERROR; } - -void HWComposer::setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled) { +void HWComposer::setVsyncEnabled(DisplayId displayId, HWC2::Vsync enabled) { RETURN_IF_INVALID_DISPLAY(displayId); auto& displayData = mDisplayData[displayId]; @@ -403,37 +383,30 @@ void HWComposer::setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled) { displayData.vsyncEnabled = enabled; - char tag[16]; - snprintf(tag, sizeof(tag), "HW_VSYNC_ON_%1u", displayId); - ATRACE_INT(tag, enabled == HWC2::Vsync::Enable ? 1 : 0); + const auto tag = "HW_VSYNC_ON_" + std::to_string(displayId); + ATRACE_INT(tag.c_str(), enabled == HWC2::Vsync::Enable ? 1 : 0); } } -status_t HWComposer::setClientTarget(int32_t displayId, uint32_t slot, - const sp& acquireFence, const sp& target, - ui::Dataspace dataspace) { +status_t HWComposer::setClientTarget(DisplayId displayId, uint32_t slot, + const sp& acquireFence, const sp& target, + ui::Dataspace dataspace) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); - ALOGV("setClientTarget for display %d", displayId); + ALOGV("setClientTarget for display %" PRIu64, displayId); auto& hwcDisplay = mDisplayData[displayId].hwcDisplay; auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace); RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE); return NO_ERROR; } -status_t HWComposer::prepare(DisplayDevice& display, - std::vector& compositionData) { +status_t HWComposer::prepare(DisplayId displayId, std::vector& compositionData) { ATRACE_CALL(); - Mutex::Autolock _l(mDisplayLock); - const auto displayId = display.getId(); - if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { - ALOGV("Skipping HWComposer prepare for non-HWC display"); - return NO_ERROR; - } - RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); + Mutex::Autolock _l(mDisplayLock); + auto& displayData = mDisplayData[displayId]; auto& hwcDisplay = displayData.hwcDisplay; if (!hwcDisplay->isConnected()) { @@ -503,7 +476,8 @@ status_t HWComposer::prepare(DisplayDevice& display, changedTypes[&*hwcLayer]); compositionInfo.compositionType = changedTypes[&*hwcLayer]; compositionInfo.layer->mLayer->setCompositionType(displayId, - compositionInfo.compositionType, false); + compositionInfo.compositionType, + false); } switch (compositionInfo.compositionType) { @@ -542,49 +516,48 @@ status_t HWComposer::prepare(DisplayDevice& display, return NO_ERROR; } -bool HWComposer::hasDeviceComposition(int32_t displayId) const { - if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { +bool HWComposer::hasDeviceComposition(const std::optional& displayId) const { + if (!displayId) { // Displays without a corresponding HWC display are never composed by // the device return false; } - RETURN_IF_INVALID_DISPLAY(displayId, false); - return mDisplayData[displayId].hasDeviceComposition; + RETURN_IF_INVALID_DISPLAY(*displayId, false); + return mDisplayData.at(*displayId).hasDeviceComposition; } -bool HWComposer::hasFlipClientTargetRequest(int32_t displayId) const { - if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { +bool HWComposer::hasFlipClientTargetRequest(const std::optional& displayId) const { + if (!displayId) { // Displays without a corresponding HWC display are never composed by // the device return false; } - RETURN_IF_INVALID_DISPLAY(displayId, false); - return ((static_cast(mDisplayData[displayId].displayRequests) & + RETURN_IF_INVALID_DISPLAY(*displayId, false); + return ((static_cast(mDisplayData.at(*displayId).displayRequests) & static_cast(HWC2::DisplayRequest::FlipClientTarget)) != 0); } -bool HWComposer::hasClientComposition(int32_t displayId) const { - if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { +bool HWComposer::hasClientComposition(const std::optional& displayId) const { + if (!displayId) { // Displays without a corresponding HWC display are always composed by // the client return true; } - RETURN_IF_INVALID_DISPLAY(displayId, true); - return mDisplayData[displayId].hasClientComposition; + RETURN_IF_INVALID_DISPLAY(*displayId, true); + return mDisplayData.at(*displayId).hasClientComposition; } -sp HWComposer::getPresentFence(int32_t displayId) const { +sp HWComposer::getPresentFence(DisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE); - return mDisplayData[displayId].lastPresentFence; + return mDisplayData.at(displayId).lastPresentFence; } -sp HWComposer::getLayerReleaseFence(int32_t displayId, - HWC2::Layer* layer) const { +sp HWComposer::getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const { RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE); - auto displayFences = mDisplayData[displayId].releaseFences; + auto displayFences = mDisplayData.at(displayId).releaseFences; if (displayFences.count(layer) == 0) { ALOGV("getLayerReleaseFence: Release fence not found"); return Fence::NO_FENCE; @@ -592,7 +565,7 @@ sp HWComposer::getLayerReleaseFence(int32_t displayId, return displayFences[layer]; } -status_t HWComposer::presentAndGetReleaseFences(int32_t displayId) { +status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) { ATRACE_CALL(); RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); @@ -620,8 +593,7 @@ status_t HWComposer::presentAndGetReleaseFences(int32_t displayId) { return NO_ERROR; } -status_t HWComposer::setPowerMode(int32_t displayId, int32_t intMode) { - ALOGV("setPowerMode(%d, %d)", displayId, intMode); +status_t HWComposer::setPowerMode(DisplayId displayId, int32_t intMode) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); const auto& displayData = mDisplayData[displayId]; @@ -677,7 +649,7 @@ status_t HWComposer::setPowerMode(int32_t displayId, int32_t intMode) { return NO_ERROR; } -status_t HWComposer::setActiveConfig(int32_t displayId, size_t configId) { +status_t HWComposer::setActiveConfig(DisplayId displayId, size_t configId) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); auto& displayData = mDisplayData[displayId]; @@ -691,8 +663,7 @@ status_t HWComposer::setActiveConfig(int32_t displayId, size_t configId) { return NO_ERROR; } -status_t HWComposer::setColorTransform(int32_t displayId, - const mat4& transform) { +status_t HWComposer::setColorTransform(DisplayId displayId, const mat4& transform) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); auto& displayData = mDisplayData[displayId]; @@ -704,26 +675,34 @@ status_t HWComposer::setColorTransform(int32_t displayId, return NO_ERROR; } -void HWComposer::disconnectDisplay(int32_t displayId) { +void HWComposer::disconnectDisplay(DisplayId displayId) { RETURN_IF_INVALID_DISPLAY(displayId); auto& displayData = mDisplayData[displayId]; // If this was a virtual display, add its slot back for reuse by future // virtual displays if (displayData.isVirtual) { - mFreeDisplaySlots.insert(displayId); + mFreeVirtualDisplayIds.insert(displayId); ++mRemainingHwcVirtualDisplays; } const auto hwcDisplayId = displayData.hwcDisplay->getId(); - mHwcDisplaySlots.erase(hwcDisplayId); - displayData = DisplayData(); + mPhysicalDisplayIdMap.erase(hwcDisplayId); + mDisplayData.erase(displayId); + mVSyncCounts.erase(displayId); + + // TODO(b/74619554): Select internal/external display from remaining displays. + if (hwcDisplayId == mInternalHwcDisplayId) { + mInternalHwcDisplayId.reset(); + } else if (hwcDisplayId == mExternalHwcDisplayId) { + mExternalHwcDisplayId.reset(); + } mHwcDevice->destroyDisplay(hwcDisplayId); } -status_t HWComposer::setOutputBuffer(int32_t displayId, - const sp& acquireFence, const sp& buffer) { +status_t HWComposer::setOutputBuffer(DisplayId displayId, const sp& acquireFence, + const sp& buffer) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); const auto& displayData = mDisplayData[displayId]; @@ -737,13 +716,12 @@ status_t HWComposer::setOutputBuffer(int32_t displayId, return NO_ERROR; } -void HWComposer::clearReleaseFences(int32_t displayId) { +void HWComposer::clearReleaseFences(DisplayId displayId) { RETURN_IF_INVALID_DISPLAY(displayId); mDisplayData[displayId].releaseFences.clear(); } -status_t HWComposer::getHdrCapabilities( - int32_t displayId, HdrCapabilities* outCapabilities) { +status_t HWComposer::getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); auto& hwcDisplay = mDisplayData[displayId].hwcDisplay; @@ -752,22 +730,22 @@ status_t HWComposer::getHdrCapabilities( return NO_ERROR; } -int32_t HWComposer::getSupportedPerFrameMetadata(int32_t displayId) const { +int32_t HWComposer::getSupportedPerFrameMetadata(DisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, 0); - return mDisplayData[displayId].hwcDisplay->getSupportedPerFrameMetadata(); + return mDisplayData.at(displayId).hwcDisplay->getSupportedPerFrameMetadata(); } -std::vector HWComposer::getRenderIntents(int32_t displayId, - ui::ColorMode colorMode) const { +std::vector HWComposer::getRenderIntents(DisplayId displayId, + ui::ColorMode colorMode) const { RETURN_IF_INVALID_DISPLAY(displayId, {}); std::vector renderIntents; - auto error = mDisplayData[displayId].hwcDisplay->getRenderIntents(colorMode, &renderIntents); + auto error = mDisplayData.at(displayId).hwcDisplay->getRenderIntents(colorMode, &renderIntents); RETURN_IF_HWC_ERROR(error, displayId, {}); return renderIntents; } -mat4 HWComposer::getDataspaceSaturationMatrix(int32_t displayId, ui::Dataspace dataspace) { +mat4 HWComposer::getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace) { RETURN_IF_INVALID_DISPLAY(displayId, {}); mat4 matrix; @@ -808,12 +786,67 @@ void HWComposer::dump(String8& result) const { result.append(mHwcDevice->dump().c_str()); } -std::optional -HWComposer::getHwcDisplayId(int32_t displayId) const { - if (!isValidDisplay(displayId)) { +std::optional HWComposer::toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const { + if (const auto it = mPhysicalDisplayIdMap.find(hwcDisplayId); + it != mPhysicalDisplayIdMap.end()) { + return it->second; + } + return {}; +} + +std::optional HWComposer::fromPhysicalDisplayId(DisplayId displayId) const { + if (const auto it = mDisplayData.find(displayId); + it != mDisplayData.end() && !it->second.isVirtual) { + return it->second.hwcDisplay->getId(); + } + return {}; +} + +std::optional HWComposer::onHotplugConnect(hwc2_display_t hwcDisplayId) { + if (isUsingVrComposer() && mInternalHwcDisplayId) { + ALOGE("Ignoring connection of external display %" PRIu64 " in VR mode", hwcDisplayId); + return {}; + } + + uint8_t port; + DisplayIdentificationData data; + const bool hasMultiDisplaySupport = getDisplayIdentificationData(hwcDisplayId, &port, &data); + + if (mPhysicalDisplayIdMap.empty()) { + mHasMultiDisplaySupport = hasMultiDisplaySupport; + ALOGI("Switching to %s multi-display mode", + hasMultiDisplaySupport ? "generalized" : "legacy"); + } else if (mHasMultiDisplaySupport && !hasMultiDisplaySupport) { + ALOGE("Ignoring connection of display %" PRIu64 " without identification data", + hwcDisplayId); return {}; } - return mDisplayData[displayId].hwcDisplay->getId(); + + std::optional info; + + if (mHasMultiDisplaySupport) { + info = parseDisplayIdentificationData(port, data); + ALOGE_IF(!info, "Failed to parse identification data for display %" PRIu64, hwcDisplayId); + } else if (mInternalHwcDisplayId && mExternalHwcDisplayId) { + ALOGE("Ignoring connection of tertiary display %" PRIu64, hwcDisplayId); + return {}; + } else { + ALOGW_IF(hasMultiDisplaySupport, "Ignoring identification data for display %" PRIu64, + hwcDisplayId); + port = mInternalHwcDisplayId ? HWC_DISPLAY_EXTERNAL : HWC_DISPLAY_PRIMARY; + } + + if (!mInternalHwcDisplayId) { + mInternalHwcDisplayId = hwcDisplayId; + } else if (!mExternalHwcDisplayId) { + mExternalHwcDisplayId = hwcDisplayId; + } + + if (info) return info; + + return DisplayIdentificationInfo{getFallbackDisplayId(port), + hwcDisplayId == mInternalHwcDisplayId ? "Internal display" + : "External display"}; } } // namespace android diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 5aa7185507..5074c2c49c 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -34,7 +34,8 @@ #include #include -#include +#include +#include #include #include "DisplayIdentification.h" @@ -82,101 +83,94 @@ public: bool hasCapability(HWC2::Capability capability) const; - // Attempts to allocate a virtual display. If the virtual display is created - // on the HWC device, outId will contain its HWC ID. - status_t allocateVirtualDisplay(uint32_t width, uint32_t height, - ui::PixelFormat* format, int32_t* outId); + // Attempts to allocate a virtual display and returns its ID if created on the HWC device. + std::optional allocateVirtualDisplay(uint32_t width, uint32_t height, + ui::PixelFormat* format); // Attempts to create a new layer on this display - HWC2::Layer* createLayer(int32_t displayId); + HWC2::Layer* createLayer(DisplayId displayId); // Destroy a previously created layer - void destroyLayer(int32_t displayId, HWC2::Layer* layer); + void destroyLayer(DisplayId displayId, HWC2::Layer* layer); // Asks the HAL what it can do - status_t prepare(DisplayDevice& display, - std::vector& compositionData); + status_t prepare(DisplayId displayId, std::vector& compositionData); - status_t setClientTarget(int32_t displayId, uint32_t slot, - const sp& acquireFence, - const sp& target, ui::Dataspace dataspace); + status_t setClientTarget(DisplayId displayId, uint32_t slot, const sp& acquireFence, + const sp& target, ui::Dataspace dataspace); // Present layers to the display and read releaseFences. - status_t presentAndGetReleaseFences(int32_t displayId); + status_t presentAndGetReleaseFences(DisplayId displayId); // set power mode - status_t setPowerMode(int32_t displayId, int mode); + status_t setPowerMode(DisplayId displayId, int mode); // set active config - status_t setActiveConfig(int32_t displayId, size_t configId); + status_t setActiveConfig(DisplayId displayId, size_t configId); // Sets a color transform to be applied to the result of composition - status_t setColorTransform(int32_t displayId, const mat4& transform); + status_t setColorTransform(DisplayId displayId, const mat4& transform); // reset state when an external, non-virtual display is disconnected - void disconnectDisplay(int32_t displayId); + void disconnectDisplay(DisplayId displayId); // does this display have layers handled by HWC - bool hasDeviceComposition(int32_t displayId) const; + bool hasDeviceComposition(const std::optional& displayId) const; // does this display have pending request to flip client target - bool hasFlipClientTargetRequest(int32_t displayId) const; + bool hasFlipClientTargetRequest(const std::optional& displayId) const; // does this display have layers handled by GLES - bool hasClientComposition(int32_t displayId) const; + bool hasClientComposition(const std::optional& displayId) const; // get the present fence received from the last call to present. - sp getPresentFence(int32_t displayId) const; + sp getPresentFence(DisplayId displayId) const; // Get last release fence for the given layer - sp getLayerReleaseFence(int32_t displayId, - HWC2::Layer* layer) const; + sp getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const; // Set the output buffer and acquire fence for a virtual display. // Returns INVALID_OPERATION if displayId is not a virtual display. - status_t setOutputBuffer(int32_t displayId, const sp& acquireFence, - const sp& buf); + status_t setOutputBuffer(DisplayId displayId, const sp& acquireFence, + const sp& buffer); // After SurfaceFlinger has retrieved the release fences for all the frames, // it can call this to clear the shared pointers in the release fence map - void clearReleaseFences(int32_t displayId); + void clearReleaseFences(DisplayId displayId); // Fetches the HDR capabilities of the given display - status_t getHdrCapabilities(int32_t displayId, HdrCapabilities* outCapabilities); + status_t getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities); - int32_t getSupportedPerFrameMetadata(int32_t displayId) const; + int32_t getSupportedPerFrameMetadata(DisplayId displayId) const; // Returns the available RenderIntent of the given display. - std::vector getRenderIntents(int32_t displayId, ui::ColorMode colorMode) const; + std::vector getRenderIntents(DisplayId displayId, + ui::ColorMode colorMode) const; - mat4 getDataspaceSaturationMatrix(int32_t displayId, ui::Dataspace dataspace); + mat4 getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace); // Events handling --------------------------------------------------------- - // Returns true if successful, false otherwise. The - // DisplayDevice::DisplayType of the display is returned as an output param. - bool onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp, int32_t* outDisplay); - std::optional onHotplug(hwc2_display_t hwcDisplayId, int32_t displayType, - HWC2::Connection connection); + // Returns stable display ID (and display name on connection of new or previously disconnected + // display), or std::nullopt if hotplug event was ignored. + std::optional onHotplug(hwc2_display_t hwcDisplayId, + HWC2::Connection connection); - void setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled); + bool onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp); + void setVsyncEnabled(DisplayId displayId, HWC2::Vsync enabled); - // Query display parameters. Pass in a display index (e.g. - // HWC_DISPLAY_PRIMARY). - nsecs_t getRefreshTimestamp(int32_t displayId) const; - bool isConnected(int32_t displayId) const; + nsecs_t getRefreshTimestamp(DisplayId displayId) const; + bool isConnected(DisplayId displayId) const; // Non-const because it can update configMap inside of mDisplayData - std::vector> - getConfigs(int32_t displayId) const; + std::vector> getConfigs(DisplayId displayId) const; - std::shared_ptr - getActiveConfig(int32_t displayId) const; - int getActiveConfigIndex(int32_t displayId) const; + std::shared_ptr getActiveConfig(DisplayId displayId) const; + int getActiveConfigIndex(DisplayId displayId) const; - std::vector getColorModes(int32_t displayId) const; + std::vector getColorModes(DisplayId displayId) const; - status_t setActiveColorMode(int32_t displayId, ui::ColorMode mode, - ui::RenderIntent renderIntent); + status_t setActiveColorMode(DisplayId displayId, ui::ColorMode mode, + ui::RenderIntent renderIntent); bool isUsingVrComposer() const; @@ -185,12 +179,19 @@ public: android::Hwc2::Composer* getComposer() const { return mHwcDevice->getComposer(); } - std::optional getHwcDisplayId(int32_t displayId) const; + // TODO(b/74619554): Remove special cases for internal/external display. + std::optional getInternalHwcDisplayId() const { return mInternalHwcDisplayId; } + std::optional getExternalHwcDisplayId() const { return mExternalHwcDisplayId; } + + std::optional toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const; + std::optional fromPhysicalDisplayId(DisplayId displayId) const; + private: // For unit tests friend TestableSurfaceFlinger; - bool isValidDisplay(int32_t displayId) const; + std::optional onHotplugConnect(hwc2_display_t hwcDisplayId); + static void validateChange(HWC2::Composition from, HWC2::Composition to); struct cb_context; @@ -215,25 +216,30 @@ private: HWC2::Error presentError; }; - std::vector mDisplayData{HWC_NUM_PHYSICAL_DISPLAY_TYPES}; + std::unordered_map mDisplayData; // This must be destroyed before mDisplayData, because destructor may call back into HWComposer // and look up DisplayData. std::unique_ptr mHwcDevice; - std::set mFreeDisplaySlots; - std::unordered_map mHwcDisplaySlots; + std::unordered_map mPhysicalDisplayIdMap; + std::optional mInternalHwcDisplayId; + std::optional mExternalHwcDisplayId; + bool mHasMultiDisplaySupport = false; + // protect mDisplayData from races between prepare and dump mutable Mutex mDisplayLock; cb_context* mCBContext = nullptr; - size_t mVSyncCounts[HWC_NUM_PHYSICAL_DISPLAY_TYPES]{0, 0}; + std::unordered_map mVSyncCounts; + + std::unordered_set mFreeVirtualDisplayIds; + uint32_t mNextVirtualDisplayId = 0; uint32_t mRemainingHwcVirtualDisplays{mHwcDevice->getMaxVirtualDisplayCount()}; // protected by mLock mutable Mutex mLock; - mutable std::unordered_map mLastHwVSync{ - {{HWC_DISPLAY_PRIMARY, 0}, {HWC_DISPLAY_EXTERNAL, 0}}}; + mutable std::unordered_map mLastHwVSync; // thread-safe mutable Mutex mVsyncLock; diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index c111a27f51..27d3dc5609 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -48,34 +48,34 @@ static const char* dbgCompositionTypeStr(DisplaySurface::CompositionType type) { } } -VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, - const sp& sink, - const sp& bqProducer, - const sp& bqConsumer, - const std::string& name) -: ConsumerBase(bqConsumer), - mHwc(hwc), - mDisplayId(dispId), - mDisplayName(name), - mSource{}, - mDefaultOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED), - mOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED), - mOutputUsage(GRALLOC_USAGE_HW_COMPOSER), - mProducerSlotSource(0), - mProducerBuffers(), - mQueueBufferOutput(), - mSinkBufferWidth(0), - mSinkBufferHeight(0), - mCompositionType(COMPOSITION_UNKNOWN), - mFbFence(Fence::NO_FENCE), - mOutputFence(Fence::NO_FENCE), - mFbProducerSlot(BufferQueue::INVALID_BUFFER_SLOT), - mOutputProducerSlot(BufferQueue::INVALID_BUFFER_SLOT), - mDbgState(DBG_STATE_IDLE), - mDbgLastCompositionType(COMPOSITION_UNKNOWN), - mMustRecompose(false), - mForceHwcCopy(SurfaceFlinger::useHwcForRgbToYuv) -{ +VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, + const std::optional& displayId, + const sp& sink, + const sp& bqProducer, + const sp& bqConsumer, + const std::string& name) + : ConsumerBase(bqConsumer), + mHwc(hwc), + mDisplayId(displayId), + mDisplayName(name), + mSource{}, + mDefaultOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED), + mOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED), + mOutputUsage(GRALLOC_USAGE_HW_COMPOSER), + mProducerSlotSource(0), + mProducerBuffers(), + mQueueBufferOutput(), + mSinkBufferWidth(0), + mSinkBufferHeight(0), + mCompositionType(COMPOSITION_UNKNOWN), + mFbFence(Fence::NO_FENCE), + mOutputFence(Fence::NO_FENCE), + mFbProducerSlot(BufferQueue::INVALID_BUFFER_SLOT), + mOutputProducerSlot(BufferQueue::INVALID_BUFFER_SLOT), + mDbgState(DBG_STATE_IDLE), + mDbgLastCompositionType(COMPOSITION_UNKNOWN), + mMustRecompose(false), + mForceHwcCopy(SurfaceFlinger::useHwcForRgbToYuv) { mSource[SOURCE_SINK] = sink; mSource[SOURCE_SCRATCH] = bqProducer; @@ -116,8 +116,9 @@ VirtualDisplaySurface::~VirtualDisplaySurface() { } status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) { - if (mDisplayId < 0) + if (!mDisplayId) { return NO_ERROR; + } mMustRecompose = mustRecompose; @@ -129,8 +130,9 @@ status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) { } status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) { - if (mDisplayId < 0) + if (!mDisplayId) { return NO_ERROR; + } VDS_LOGW_IF(mDbgState != DBG_STATE_BEGUN, "Unexpected prepareFrame() in %s state", dbgStateStr()); @@ -177,8 +179,9 @@ status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) { } status_t VirtualDisplaySurface::advanceFrame() { - if (mDisplayId < 0) + if (!mDisplayId) { return NO_ERROR; + } if (mCompositionType == COMPOSITION_HWC) { VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED, @@ -211,7 +214,7 @@ status_t VirtualDisplaySurface::advanceFrame() { // At this point we know the output buffer acquire fence, // so update HWC state with it. - mHwc.setOutputBuffer(mDisplayId, mOutputFence, outBuffer); + mHwc.setOutputBuffer(*mDisplayId, mOutputFence, outBuffer); status_t result = NO_ERROR; if (fbBuffer != nullptr) { @@ -221,22 +224,23 @@ status_t VirtualDisplaySurface::advanceFrame() { &hwcSlot, &hwcBuffer); // TODO: Correctly propagate the dataspace from GL composition - result = mHwc.setClientTarget(mDisplayId, hwcSlot, mFbFence, - hwcBuffer, ui::Dataspace::UNKNOWN); + result = mHwc.setClientTarget(*mDisplayId, hwcSlot, mFbFence, hwcBuffer, + ui::Dataspace::UNKNOWN); } return result; } void VirtualDisplaySurface::onFrameCommitted() { - if (mDisplayId < 0) + if (!mDisplayId) { return; + } VDS_LOGW_IF(mDbgState != DBG_STATE_HWC, "Unexpected onFrameCommitted() in %s state", dbgStateStr()); mDbgState = DBG_STATE_IDLE; - sp retireFence = mHwc.getPresentFence(mDisplayId); + sp retireFence = mHwc.getPresentFence(*mDisplayId); if (mCompositionType == COMPOSITION_MIXED && mFbProducerSlot >= 0) { // release the scratch buffer back to the pool Mutex::Autolock lock(mMutex); @@ -291,8 +295,9 @@ const sp& VirtualDisplaySurface::getClientTargetAcquireFence() const { status_t VirtualDisplaySurface::requestBuffer(int pslot, sp* outBuf) { - if (mDisplayId < 0) + if (!mDisplayId) { return mSource[SOURCE_SINK]->requestBuffer(pslot, outBuf); + } VDS_LOGW_IF(mDbgState != DBG_STATE_GLES, "Unexpected requestBuffer pslot=%d in %s state", @@ -313,7 +318,7 @@ status_t VirtualDisplaySurface::setAsyncMode(bool async) { status_t VirtualDisplaySurface::dequeueBuffer(Source source, PixelFormat format, uint64_t usage, int* sslot, sp* fence) { - LOG_FATAL_IF(mDisplayId < 0, "mDisplayId=%d but should not be < 0.", mDisplayId); + LOG_FATAL_IF(!mDisplayId); status_t result = mSource[source]->dequeueBuffer(sslot, fence, mSinkBufferWidth, mSinkBufferHeight, @@ -359,7 +364,7 @@ status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp* fence, uint PixelFormat format, uint64_t usage, uint64_t* outBufferAge, FrameEventHistoryDelta* outTimestamps) { - if (mDisplayId < 0) { + if (!mDisplayId) { return mSource[SOURCE_SINK]->dequeueBuffer(pslot, fence, w, h, format, usage, outBufferAge, outTimestamps); } @@ -446,8 +451,9 @@ status_t VirtualDisplaySurface::attachBuffer(int* /* outSlot */, status_t VirtualDisplaySurface::queueBuffer(int pslot, const QueueBufferInput& input, QueueBufferOutput* output) { - if (mDisplayId < 0) + if (!mDisplayId) { return mSource[SOURCE_SINK]->queueBuffer(pslot, input, output); + } VDS_LOGW_IF(mDbgState != DBG_STATE_GLES, "Unexpected queueBuffer(pslot=%d) in %s state", pslot, @@ -504,8 +510,9 @@ status_t VirtualDisplaySurface::queueBuffer(int pslot, status_t VirtualDisplaySurface::cancelBuffer(int pslot, const sp& fence) { - if (mDisplayId < 0) + if (!mDisplayId) { return mSource[SOURCE_SINK]->cancelBuffer(mapProducer2SourceSlot(SOURCE_SINK, pslot), fence); + } VDS_LOGW_IF(mDbgState != DBG_STATE_GLES, "Unexpected cancelBuffer(pslot=%d) in %s state", pslot, @@ -616,6 +623,8 @@ void VirtualDisplaySurface::resetPerFrameState() { } status_t VirtualDisplaySurface::refreshOutputBuffer() { + LOG_FATAL_IF(!mDisplayId); + if (mOutputProducerSlot >= 0) { mSource[SOURCE_SINK]->cancelBuffer( mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot), @@ -633,8 +642,8 @@ status_t VirtualDisplaySurface::refreshOutputBuffer() { // until after GLES calls queueBuffer(). So here we just set the buffer // (for use in HWC prepare) but not the fence; we'll call this again with // the proper fence once we have it. - result = mHwc.setOutputBuffer(mDisplayId, Fence::NO_FENCE, - mProducerBuffers[mOutputProducerSlot]); + result = mHwc.setOutputBuffer(*mDisplayId, Fence::NO_FENCE, + mProducerBuffers[mOutputProducerSlot]); return result; } diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index 4bd4d0fe61..33678df963 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -17,8 +17,10 @@ #ifndef ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H #define ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H +#include #include +#include "DisplayIdentification.h" #include "DisplaySurface.h" #include "HWComposerBufferCache.h" @@ -75,11 +77,10 @@ class VirtualDisplaySurface : public DisplaySurface, public BnGraphicBufferProducer, private ConsumerBase { public: - VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, - const sp& sink, - const sp& bqProducer, - const sp& bqConsumer, - const std::string& name); + VirtualDisplaySurface(HWComposer& hwc, const std::optional& displayId, + const sp& sink, + const sp& bqProducer, + const sp& bqConsumer, const std::string& name); // // DisplaySurface interface @@ -154,7 +155,7 @@ private: // Immutable after construction // HWComposer& mHwc; - const int32_t mDisplayId; + const std::optional mDisplayId; const std::string mDisplayName; sp mSource[2]; // indexed by SOURCE_* uint32_t mDefaultOutputFormat; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f29dfc0f1b..f41a753a7a 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -196,9 +196,9 @@ sp Layer::getHandle() { // h/w composer set-up // --------------------------------------------------------------------------- -bool Layer::createHwcLayer(HWComposer* hwc, int32_t displayId) { +bool Layer::createHwcLayer(HWComposer* hwc, DisplayId displayId) { LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(displayId) != 0, - "Already have a layer for display %d", displayId); + "Already have a layer for display %" PRIu64, displayId); auto layer = std::shared_ptr( hwc->createLayer(displayId), [hwc, displayId](HWC2::Layer* layer) { @@ -214,7 +214,7 @@ bool Layer::createHwcLayer(HWComposer* hwc, int32_t displayId) { return true; } -bool Layer::destroyHwcLayer(int32_t displayId) { +bool Layer::destroyHwcLayer(DisplayId displayId) { if (getBE().mHwcLayers.count(displayId) == 0) { return false; } @@ -461,12 +461,13 @@ FloatRect Layer::computeCrop(const sp& display) const { void Layer::setGeometry(const sp& display, uint32_t z) { const auto displayId = display->getId(); - if (!hasHwcLayer(displayId)) { - ALOGE("[%s] failed to setGeometry: no HWC layer found (%d)", - mName.string(), displayId); + LOG_ALWAYS_FATAL_IF(!displayId); + if (!hasHwcLayer(*displayId)) { + ALOGE("[%s] failed to setGeometry: no HWC layer found for display %" PRIu64, mName.string(), + *displayId); return; } - auto& hwcInfo = getBE().mHwcLayers[displayId]; + auto& hwcInfo = getBE().mHwcLayers[*displayId]; // enable this layer hwcInfo.forceClientComposition = false; @@ -618,7 +619,7 @@ void Layer::setGeometry(const sp& display, uint32_t z) { if (orientation & ui::Transform::ROT_INVALID) { // we can only handle simple transformation hwcInfo.forceClientComposition = true; - getBE().mHwcLayers[displayId].compositionType = HWC2::Composition::Client; + getBE().mHwcLayers[*displayId].compositionType = HWC2::Composition::Client; } else { auto transform = static_cast(orientation); hwcInfo.transform = transform; @@ -632,18 +633,18 @@ void Layer::setGeometry(const sp& display, uint32_t z) { } } -void Layer::forceClientComposition(int32_t displayId) { +void Layer::forceClientComposition(DisplayId displayId) { if (getBE().mHwcLayers.count(displayId) == 0) { - ALOGE("forceClientComposition: no HWC layer found (%d)", displayId); + ALOGE("forceClientComposition: no HWC layer found (display %" PRIu64 ")", displayId); return; } getBE().mHwcLayers[displayId].forceClientComposition = true; } -bool Layer::getForceClientComposition(int32_t displayId) { +bool Layer::getForceClientComposition(DisplayId displayId) { if (getBE().mHwcLayers.count(displayId) == 0) { - ALOGE("getForceClientComposition: no HWC layer found (%d)", displayId); + ALOGE("getForceClientComposition: no HWC layer found (display %" PRIu64 ")", displayId); return false; } @@ -652,7 +653,7 @@ bool Layer::getForceClientComposition(int32_t displayId) { void Layer::updateCursorPosition(const sp& display) { const auto displayId = display->getId(); - if (getBE().mHwcLayers.count(displayId) == 0 || + if (getBE().mHwcLayers.count(*displayId) == 0 || getCompositionType(displayId) != HWC2::Composition::Cursor) { return; } @@ -675,8 +676,8 @@ void Layer::updateCursorPosition(const sp& display) { auto position = displayTransform.transform(frame); auto error = - (getBE().mHwcLayers[displayId].layer)->setCursorPosition( - position.left, position.top); + getBE().mHwcLayers[*displayId].layer->setCursorPosition(position.left, position.top); + ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set cursor position " "to (%d, %d): %s (%d)", @@ -708,7 +709,7 @@ void Layer::clearWithOpenGL(const RenderArea& renderArea) const { clearWithOpenGL(renderArea, 0, 0, 0, 0); } -void Layer::setCompositionType(int32_t displayId, HWC2::Composition type, bool callIntoHwc) { +void Layer::setCompositionType(DisplayId displayId, HWC2::Composition type, bool callIntoHwc) { if (getBE().mHwcLayers.count(displayId) == 0) { ALOGE("setCompositionType called without a valid HWC layer"); return; @@ -731,16 +732,20 @@ void Layer::setCompositionType(int32_t displayId, HWC2::Composition type, bool c } } -HWC2::Composition Layer::getCompositionType(int32_t displayId) const { - if (getBE().mHwcLayers.count(displayId) == 0) { +HWC2::Composition Layer::getCompositionType(const std::optional& displayId) const { + if (!displayId) { // If we're querying the composition type for a display that does not // have a HWC counterpart, then it will always be Client return HWC2::Composition::Client; } - return getBE().mHwcLayers[displayId].compositionType; + if (getBE().mHwcLayers.count(*displayId) == 0) { + ALOGE("getCompositionType called with an invalid HWC layer"); + return HWC2::Composition::Invalid; + } + return getBE().mHwcLayers.at(*displayId).compositionType; } -void Layer::setClearClientTarget(int32_t displayId, bool clear) { +void Layer::setClearClientTarget(DisplayId displayId, bool clear) { if (getBE().mHwcLayers.count(displayId) == 0) { ALOGE("setClearClientTarget called without a valid HWC layer"); return; @@ -748,7 +753,7 @@ void Layer::setClearClientTarget(int32_t displayId, bool clear) { getBE().mHwcLayers[displayId].clearClientTarget = clear; } -bool Layer::getClearClientTarget(int32_t displayId) const { +bool Layer::getClearClientTarget(DisplayId displayId) const { if (getBE().mHwcLayers.count(displayId) == 0) { ALOGE("getClearClientTarget called without a valid HWC layer"); return false; @@ -1416,7 +1421,7 @@ void Layer::miniDumpHeader(String8& result) { result.append("-----------------------------\n"); } -void Layer::miniDump(String8& result, int32_t displayId) const { +void Layer::miniDump(String8& result, DisplayId displayId) const { if (getBE().mHwcLayers.count(displayId) == 0) { return; } @@ -1980,7 +1985,7 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) } } -void Layer::writeToProto(LayerProto* layerInfo, int32_t displayId) { +void Layer::writeToProto(LayerProto* layerInfo, DisplayId displayId) { if (!hasHwcLayer(displayId)) { return; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 6921ca9b04..ced6532505 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -38,6 +38,7 @@ #include #include +#include #include #include "Client.h" @@ -351,7 +352,7 @@ public: void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing); - void writeToProto(LayerProto* layerInfo, int32_t displayId); + void writeToProto(LayerProto* layerInfo, DisplayId displayId); virtual Geometry getActiveGeometry(const Layer::State& s) const { return s.active_legacy; } virtual uint32_t getActiveWidth(const Layer::State& s) const { return s.active_legacy.w; } @@ -377,16 +378,17 @@ public: virtual bool isHdrY410() const { return false; } void setGeometry(const sp& display, uint32_t z); - void forceClientComposition(int32_t displayId); - bool getForceClientComposition(int32_t displayId); - virtual void setPerFrameData(const sp& display) = 0; + void forceClientComposition(DisplayId displayId); + bool getForceClientComposition(DisplayId displayId); + virtual void setPerFrameData(DisplayId displayId, const ui::Transform& transform, + const Rect& viewport, int32_t supportedPerFrameMetadata) = 0; // callIntoHwc exists so we can update our local state and call // acceptDisplayChanges without unnecessarily updating the device's state - void setCompositionType(int32_t displayId, HWC2::Composition type, bool callIntoHwc = true); - HWC2::Composition getCompositionType(int32_t displayId) const; - void setClearClientTarget(int32_t displayId, bool clear); - bool getClearClientTarget(int32_t displayId) const; + void setCompositionType(DisplayId displayId, HWC2::Composition type, bool callIntoHwc = true); + HWC2::Composition getCompositionType(const std::optional& displayId) const; + void setClearClientTarget(DisplayId displayId, bool clear); + bool getClearClientTarget(DisplayId displayId) const; void updateCursorPosition(const sp& display); /* @@ -407,7 +409,8 @@ public: * called after composition. * returns true if the layer latched a new buffer this frame. */ - virtual bool onPostComposition(const std::shared_ptr& /*glDoneFence*/, + virtual bool onPostComposition(const std::optional& /*displayId*/, + const std::shared_ptr& /*glDoneFence*/, const std::shared_ptr& /*presentFence*/, const CompositorTiming& /*compositorTiming*/) { return false; @@ -492,24 +495,24 @@ public: // ----------------------------------------------------------------------- - bool createHwcLayer(HWComposer* hwc, int32_t displayId); - bool destroyHwcLayer(int32_t displayId); + bool createHwcLayer(HWComposer* hwc, DisplayId displayId); + bool destroyHwcLayer(DisplayId displayId); void destroyAllHwcLayers(); - bool hasHwcLayer(int32_t displayId) { return getBE().mHwcLayers.count(displayId) > 0; } + bool hasHwcLayer(DisplayId displayId) { return getBE().mHwcLayers.count(displayId) > 0; } - HWC2::Layer* getHwcLayer(int32_t displayId) { - if (getBE().mHwcLayers.count(displayId) == 0) { + HWC2::Layer* getHwcLayer(DisplayId displayId) { + if (!hasHwcLayer(displayId)) { return nullptr; } return getBE().mHwcLayers[displayId].layer.get(); } - bool setHwcLayer(int32_t hwcId) { - if (getBE().mHwcLayers.count(hwcId) == 0) { + bool setHwcLayer(DisplayId displayId) { + if (!hasHwcLayer(displayId)) { return false; } - getBE().compositionInfo.hwc.hwcLayer = getBE().mHwcLayers[hwcId].layer; + getBE().compositionInfo.hwc.hwcLayer = getBE().mHwcLayers[displayId].layer; return true; } @@ -524,7 +527,7 @@ public: /* always call base class first */ static void miniDumpHeader(String8& result); - void miniDump(String8& result, int32_t displayId) const; + void miniDump(String8& result, DisplayId displayId) const; void dumpFrameStats(String8& result) const; void dumpFrameEvents(String8& result); void clearFrameStats(); diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h index 463c46c285..3f5134ecdc 100644 --- a/services/surfaceflinger/LayerBE.h +++ b/services/surfaceflinger/LayerBE.h @@ -24,6 +24,7 @@ #include #include +#include "DisplayHardware/DisplayIdentification.h" #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/HWComposerBufferCache.h" #include "SurfaceFlinger.h" @@ -41,7 +42,7 @@ struct CompositionInfo { std::shared_ptr layer; struct { std::shared_ptr hwcLayer; - int32_t displayId = -1; + DisplayId displayId; sp fence; HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid; Rect displayFrame; @@ -123,12 +124,11 @@ private: HWC2::Transform transform; }; - // A layer can be attached to multiple displays when operating in mirror mode // (a.k.a: when several displays are attached with equal layerStack). In this // case we need to keep track. In non-mirror mode, a layer will have only one - // HWCInfo. This map key is a display layerStack. - std::unordered_map mHwcLayers; + // HWCInfo. + std::unordered_map mHwcLayers; CompositionInfo compositionInfo; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index dec08fd629..137d91bf2b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -105,8 +105,6 @@ #include -#define DISPLAY_COUNT 1 - namespace android { using namespace android::hardware::configstore; @@ -247,7 +245,6 @@ SurfaceFlinger::SurfaceFlinger(surfaceflinger::Factory& factory, mLayersRemoved(false), mLayersAdded(false), mBootTime(systemTime()), - mDisplayTokens(), mVisibleRegionsDirty(false), mGeometryInvalid(false), mAnimCompositionPending(false), @@ -482,40 +479,49 @@ sp SurfaceFlinger::createDisplay(const String8& displayName, sp token = new DisplayToken(this); Mutex::Autolock _l(mStateLock); - DisplayDeviceState info; - info.type = DisplayDevice::DISPLAY_VIRTUAL; - info.displayName = displayName; - info.isSecure = secure; - mCurrentState.displays.add(token, info); - mInterceptor->saveDisplayCreation(info); + // Display ID is assigned when virtual display is allocated by HWC. + DisplayDeviceState state; + state.isSecure = secure; + state.displayName = displayName; + mCurrentState.displays.add(token, state); + mInterceptor->saveDisplayCreation(state); return token; } void SurfaceFlinger::destroyDisplay(const sp& displayToken) { Mutex::Autolock _l(mStateLock); - ssize_t idx = mCurrentState.displays.indexOfKey(displayToken); - if (idx < 0) { + ssize_t index = mCurrentState.displays.indexOfKey(displayToken); + if (index < 0) { ALOGE("destroyDisplay: Invalid display token %p", displayToken.get()); return; } - const DisplayDeviceState& info(mCurrentState.displays.valueAt(idx)); - if (!info.isVirtual()) { + const DisplayDeviceState& state = mCurrentState.displays.valueAt(index); + if (!state.isVirtual()) { ALOGE("destroyDisplay called for non-virtual display"); return; } - mInterceptor->saveDisplayDeletion(info.sequenceId); - mCurrentState.displays.removeItemsAt(idx); + mInterceptor->saveDisplayDeletion(state.sequenceId); + mCurrentState.displays.removeItemsAt(index); setTransactionFlags(eDisplayTransactionNeeded); } sp SurfaceFlinger::getBuiltInDisplay(int32_t id) { - if (uint32_t(id) >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) { - ALOGE("getDefaultDisplay: id=%d is not a valid default display id", id); + std::optional displayId; + + if (id == HWC_DISPLAY_PRIMARY) { + displayId = getInternalDisplayId(); + } else if (id == HWC_DISPLAY_EXTERNAL) { + displayId = getExternalDisplayId(); + } + + if (!displayId) { + ALOGE("%s: Invalid display %d", __FUNCTION__, id); return nullptr; } - return mDisplayTokens[id]; + + return getPhysicalDisplayToken(*displayId); } status_t SurfaceFlinger::getColorManagement(bool* outGetColorManagement) const { @@ -598,8 +604,10 @@ void SurfaceFlinger::init() { // start the EventThread if (mUseScheduler) { - mScheduler = getFactory().createScheduler( - [this](bool enabled) { setVsyncEnabled(HWC_DISPLAY_PRIMARY, enabled); }); + mScheduler = getFactory().createScheduler([this](bool enabled) { + setVsyncEnabled(EventThread::DisplayType::Primary, enabled); + }); + mAppConnectionHandle = mScheduler->createConnection("appConnection", SurfaceFlinger::vsyncPhaseOffsetNs, [this] { resyncWithRateLimit(); }, @@ -659,7 +667,7 @@ void SurfaceFlinger::init() { processDisplayHotplugEventsLocked(); const auto display = getDefaultDisplayDeviceLocked(); LOG_ALWAYS_FATAL_IF(!display, "Missing internal display after registering composer callback."); - LOG_ALWAYS_FATAL_IF(!getHwComposer().isConnected(display->getId()), + LOG_ALWAYS_FATAL_IF(!getHwComposer().isConnected(*display->getId()), "Internal display is disconnected."); // make the default display GLContext current so that we can create textures @@ -682,7 +690,7 @@ void SurfaceFlinger::init() { }; mVrFlinger = dvr::VrFlinger::Create(getHwComposer().getComposer(), getHwComposer() - .getHwcDisplayId(display->getId()) + .fromPhysicalDisplayId(*display->getId()) .value_or(0), vrFlingerRequestDisplayCallback); if (!mVrFlinger) { @@ -691,7 +699,7 @@ void SurfaceFlinger::init() { } mEventControlThread = getFactory().createEventControlThread( - [this](bool enabled) { setVsyncEnabled(HWC_DISPLAY_PRIMARY, enabled); }); + [this](bool enabled) { setVsyncEnabled(EventThread::DisplayType::Primary, enabled); }); // initialize our drawing state mDrawingState = mCurrentState; @@ -717,8 +725,8 @@ void SurfaceFlinger::init() { // and apply this saturation matrix on Display P3 content. Unless the risk of applying // such saturation matrix on Display P3 is understood fully, the API should always return // identify matrix. - mEnhancedSaturationMatrix = getBE().mHwc->getDataspaceSaturationMatrix(display->getId(), - Dataspace::SRGB_LINEAR); + mEnhancedSaturationMatrix = + getHwComposer().getDataspaceSaturationMatrix(*display->getId(), Dataspace::SRGB_LINEAR); // we will apply this on Display P3. if (mEnhancedSaturationMatrix != mat4()) { @@ -805,16 +813,9 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, return BAD_VALUE; } - int32_t type = NAME_NOT_FOUND; - for (int i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; ++i) { - if (displayToken == mDisplayTokens[i]) { - type = i; - break; - } - } - - if (type < 0) { - return type; + const auto displayId = getPhysicalDisplayId(displayToken); + if (!displayId) { + return NAME_NOT_FOUND; } // TODO: Not sure if display density should handled by SF any longer @@ -838,7 +839,7 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, ConditionalLock _l(mStateLock, std::this_thread::get_id() != mMainThreadId); - for (const auto& hwConfig : getHwComposer().getConfigs(type)) { + for (const auto& hwConfig : getHwComposer().getConfigs(*displayId)) { DisplayInfo info = DisplayInfo(); float xdpi = hwConfig->getDpiX(); @@ -850,7 +851,7 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, info.viewportW = info.w; info.viewportH = info.h; - if (type == DisplayDevice::DISPLAY_PRIMARY) { + if (displayId == getInternalDisplayId()) { // The density of the device is provided by a build property float density = Density::getBuildDensity() / 160.0f; if (density == 0) { @@ -906,7 +907,7 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, // All non-virtual displays are currently considered secure. info.secure = true; - if (type == DisplayDevice::DISPLAY_PRIMARY && + if (displayId == getInternalDisplayId() && primaryDisplayOrientation & DisplayState::eOrientationSwapMask) { std::swap(info.w, info.h); } @@ -922,7 +923,6 @@ status_t SurfaceFlinger::getDisplayStats(const sp&, DisplayStatInfo* st return BAD_VALUE; } - // FIXME for now we always return stats for the primary display. if (mUseScheduler) { mScheduler->getDisplayStatInfo(stats); } else { @@ -943,18 +943,21 @@ int SurfaceFlinger::getActiveConfig(const sp& displayToken) { } void SurfaceFlinger::setActiveConfigInternal(const sp& display, int mode) { - int currentMode = display->getActiveConfig(); - if (mode == currentMode) { + if (display->isVirtual()) { + ALOGE("%s: Invalid operation on virtual display", __FUNCTION__); return; } - if (display->isVirtual()) { - ALOGW("Trying to set config for virtual display"); + int currentMode = display->getActiveConfig(); + if (mode == currentMode) { return; } + const auto displayId = display->getId(); + LOG_ALWAYS_FATAL_IF(!displayId); + display->setActiveConfig(mode); - getHwComposer().setActiveConfig(display->getDisplayType(), mode); + getHwComposer().setActiveConfig(*displayId, mode); } status_t SurfaceFlinger::setActiveConfig(const sp& displayToken, int mode) { @@ -979,29 +982,23 @@ status_t SurfaceFlinger::setActiveConfig(const sp& displayToken, int mo return NO_ERROR; } + status_t SurfaceFlinger::getDisplayColorModes(const sp& displayToken, Vector* outColorModes) { if (!displayToken || !outColorModes) { return BAD_VALUE; } - int32_t type = NAME_NOT_FOUND; - for (int i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; ++i) { - if (displayToken == mDisplayTokens[i]) { - type = i; - break; - } - } - - if (type < 0) { - return type; + const auto displayId = getPhysicalDisplayId(displayToken); + if (!displayId) { + return NAME_NOT_FOUND; } std::vector modes; { ConditionalLock _l(mStateLock, std::this_thread::get_id() != mMainThreadId); - modes = getHwComposer().getColorModes(type); + modes = getHwComposer().getColorModes(*displayId); } outColorModes->clear(); std::copy(modes.cbegin(), modes.cend(), std::back_inserter(*outColorModes)); @@ -1018,6 +1015,11 @@ ColorMode SurfaceFlinger::getActiveColorMode(const sp& displayToken) { void SurfaceFlinger::setActiveColorModeInternal(const sp& display, ColorMode mode, Dataspace dataSpace, RenderIntent renderIntent) { + if (display->isVirtual()) { + ALOGE("%s: Invalid operation on virtual display", __FUNCTION__); + return; + } + ColorMode currentMode = display->getActiveColorMode(); Dataspace currentDataSpace = display->getCompositionDataSpace(); RenderIntent currentRenderIntent = display->getActiveRenderIntent(); @@ -1027,19 +1029,17 @@ void SurfaceFlinger::setActiveColorModeInternal(const sp& display return; } - if (display->isVirtual()) { - ALOGW("Trying to set config for virtual display"); - return; - } - display->setActiveColorMode(mode); display->setCompositionDataSpace(dataSpace); display->setActiveRenderIntent(renderIntent); - getHwComposer().setActiveColorMode(display->getDisplayType(), mode, renderIntent); - ALOGV("Set active color mode: %s (%d), active render intent: %s (%d), type=%d", + const auto displayId = display->getId(); + LOG_ALWAYS_FATAL_IF(!displayId); + getHwComposer().setActiveColorMode(*displayId, mode, renderIntent); + + ALOGV("Set active color mode: %s (%d), active render intent: %s (%d), display=%" PRIu64, decodeColorMode(mode).c_str(), mode, decodeRenderIntent(renderIntent).c_str(), - renderIntent, display->getDisplayType()); + renderIntent, *displayId); } status_t SurfaceFlinger::setActiveColorMode(const sp& displayToken, ColorMode mode) { @@ -1255,12 +1255,12 @@ void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) { return; } - const auto displayId = DisplayDevice::DISPLAY_PRIMARY; - if (!getHwComposer().isConnected(displayId)) { + const auto displayId = getInternalDisplayId(); + if (!displayId || !getHwComposer().isConnected(*displayId)) { return; } - const auto activeConfig = getHwComposer().getActiveConfig(displayId); + const auto activeConfig = getHwComposer().getActiveConfig(*displayId); const nsecs_t period = activeConfig->getVsyncPeriod(); if (mUseScheduler) { @@ -1311,12 +1311,11 @@ void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDispl return; } - int32_t type; - if (!getBE().mHwc->onVsync(hwcDisplayId, timestamp, &type)) { + if (!getHwComposer().onVsync(hwcDisplayId, timestamp)) { return; } - if (type != DisplayDevice::DISPLAY_PRIMARY) { + if (hwcDisplayId != getHwComposer().getInternalHwcDisplayId()) { // For now, we don't do anything with external display vsyncs. return; } @@ -1379,11 +1378,13 @@ void SurfaceFlinger::onRefreshReceived(int sequenceId, hwc2_display_t /*hwcDispl repaintEverything(); } -void SurfaceFlinger::setVsyncEnabled(int disp, int enabled) { +void SurfaceFlinger::setVsyncEnabled(EventThread::DisplayType /*displayType*/, bool enabled) { ATRACE_CALL(); Mutex::Autolock lock(mStateLock); - getHwComposer().setVsyncEnabled(disp, - enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable); + if (const auto displayId = getInternalDisplayId()) { + getHwComposer().setVsyncEnabled(*displayId, + enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable); + } } // Note: it is assumed the caller holds |mStateLock| when this is called @@ -1454,7 +1455,7 @@ void SurfaceFlinger::updateVrFlinger() { setPowerModeInternal(display, currentDisplayPowerMode, /*stateLockHeld*/ true); // Reset the timing values to account for the period of the swapped in HWC - const auto activeConfig = getHwComposer().getActiveConfig(display->getId()); + const auto activeConfig = getHwComposer().getActiveConfig(*display->getId()); const nsecs_t period = activeConfig->getVsyncPeriod(); mAnimFrameTracker.setDisplayRefreshPeriod(period); @@ -1595,24 +1596,25 @@ void SurfaceFlinger::calculateWorkingSet() { mGeometryInvalid = false; for (const auto& [token, display] : mDisplays) { const auto displayId = display->getId(); - if (displayId >= 0) { - const Vector>& currentLayers( - display->getVisibleLayersSortedByZ()); - for (size_t i = 0; i < currentLayers.size(); i++) { - const auto& layer = currentLayers[i]; - - if (!layer->hasHwcLayer(displayId)) { - if (!layer->createHwcLayer(getBE().mHwc.get(), displayId)) { - layer->forceClientComposition(displayId); - continue; - } - } + if (!displayId) { + continue; + } - layer->setGeometry(display, i); - if (mDebugDisableHWC || mDebugRegion) { - layer->forceClientComposition(displayId); + const Vector>& currentLayers = display->getVisibleLayersSortedByZ(); + for (size_t i = 0; i < currentLayers.size(); i++) { + const auto& layer = currentLayers[i]; + + if (!layer->hasHwcLayer(*displayId)) { + if (!layer->createHwcLayer(&getHwComposer(), *displayId)) { + layer->forceClientComposition(*displayId); + continue; } } + + layer->setGeometry(display, i); + if (mDebugDisableHWC || mDebugRegion) { + layer->forceClientComposition(*displayId); + } } } } @@ -1620,41 +1622,43 @@ void SurfaceFlinger::calculateWorkingSet() { // Set the per-frame data for (const auto& [token, display] : mDisplays) { const auto displayId = display->getId(); - if (displayId < 0) { + if (!displayId) { continue; } if (mDrawingState.colorMatrixChanged) { display->setColorTransform(mDrawingState.colorMatrix); - status_t result = getBE().mHwc->setColorTransform(displayId, mDrawingState.colorMatrix); - ALOGE_IF(result != NO_ERROR, "Failed to set color transform on " - "display %d: %d", displayId, result); + status_t result = + getHwComposer().setColorTransform(*displayId, mDrawingState.colorMatrix); + ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display %" PRIu64 ": %d", + *displayId, result); } for (auto& layer : display->getVisibleLayersSortedByZ()) { if (layer->isHdrY410()) { - layer->forceClientComposition(displayId); + layer->forceClientComposition(*displayId); } else if ((layer->getDataSpace() == Dataspace::BT2020_PQ || layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) && !display->hasHDR10Support()) { - layer->forceClientComposition(displayId); + layer->forceClientComposition(*displayId); } else if ((layer->getDataSpace() == Dataspace::BT2020_HLG || layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) && !display->hasHLGSupport()) { - layer->forceClientComposition(displayId); + layer->forceClientComposition(*displayId); } // TODO(b/111562338) remove when composer 2.3 is shipped. if (layer->hasColorTransform()) { - layer->forceClientComposition(displayId); + layer->forceClientComposition(*displayId); } - if (layer->getForceClientComposition(displayId)) { + if (layer->getForceClientComposition(*displayId)) { ALOGV("[%s] Requesting Client composition", layer->getName().string()); - layer->setCompositionType(displayId, HWC2::Composition::Client); + layer->setCompositionType(*displayId, HWC2::Composition::Client); continue; } - layer->setPerFrameData(display); + layer->setPerFrameData(*displayId, display->getTransform(), display->getViewport(), + display->getSupportedPerFrameMetadata()); } if (useColorManagement) { @@ -1674,10 +1678,14 @@ void SurfaceFlinger::calculateWorkingSet() { for (auto& layer : display->getVisibleLayersSortedByZ()) { const auto displayId = display->getId(); layer->getBE().compositionInfo.compositionType = layer->getCompositionType(displayId); - if (!layer->setHwcLayer(displayId)) { - ALOGV("Need to create HWCLayer for %s", layer->getName().string()); + + if (displayId) { + if (!layer->setHwcLayer(*displayId)) { + ALOGV("Need to create HWCLayer for %s", layer->getName().string()); + } + layer->getBE().compositionInfo.hwc.displayId = *displayId; } - layer->getBE().compositionInfo.hwc.displayId = displayId; + getBE().mCompositionInfo[token].push_back(layer->getBE().compositionInfo); layer->getBE().compositionInfo.hwc.hwcLayer = nullptr; } @@ -1837,7 +1845,7 @@ void SurfaceFlinger::postComposition() getBE().mDisplayTimeline.updateSignalTimes(); mPreviousPresentFence = - display ? getHwComposer().getPresentFence(display->getId()) : Fence::NO_FENCE; + display ? getHwComposer().getPresentFence(*display->getId()) : Fence::NO_FENCE; auto presentFenceTime = std::make_shared(mPreviousPresentFence); getBE().mDisplayTimeline.push(presentFenceTime); @@ -1860,8 +1868,8 @@ void SurfaceFlinger::postComposition() } mDrawingState.traverseInZOrder([&](Layer* layer) { - bool frameLatched = layer->onPostComposition(glCompositionDoneFenceTime, - presentFenceTime, compositorTiming); + bool frameLatched = layer->onPostComposition(display->getId(), glCompositionDoneFenceTime, + presentFenceTime, compositorTiming); if (frameLatched) { recordBufferingStats(layer->getName().string(), layer->getOccupancyHistory(false)); @@ -1881,7 +1889,7 @@ void SurfaceFlinger::postComposition() } if (!hasSyncFramework) { - if (display && getHwComposer().isConnected(display->getId()) && display->isPoweredOn()) { + if (display && getHwComposer().isConnected(*display->getId()) && display->isPoweredOn()) { if (mUseScheduler) { mScheduler->enableHardwareVsync(); } else { @@ -1896,10 +1904,10 @@ void SurfaceFlinger::postComposition() if (presentFenceTime->isValid()) { mAnimFrameTracker.setActualPresentFence( std::move(presentFenceTime)); - } else if (display && getHwComposer().isConnected(display->getId())) { + } else if (display && getHwComposer().isConnected(*display->getId())) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. - const nsecs_t presentTime = getHwComposer().getRefreshTimestamp(display->getId()); + const nsecs_t presentTime = getHwComposer().getRefreshTimestamp(*display->getId()); mAnimFrameTracker.setActualPresentTime(presentTime); } mAnimFrameTracker.advanceFrame(); @@ -1912,8 +1920,7 @@ void SurfaceFlinger::postComposition() mTimeStats.setPresentFenceGlobal(presentFenceTime); - if (display && getHwComposer().isConnected(display->getId()) && - display->getPowerMode() == HWC_POWER_MODE_OFF) { + if (display && getHwComposer().isConnected(*display->getId()) && !display->isPoweredOn()) { return; } @@ -1967,6 +1974,7 @@ void SurfaceFlinger::rebuildLayerStacks() { mDrawingState.traverseInZOrder([&](Layer* layer) { bool hwcLayerDestroyed = false; + const auto displayId = display->getId(); if (layer->belongsToDisplay(display->getLayerStack(), display->isPrimary())) { Region drawRegion(tr.transform( layer->visibleNonTransparentRegion)); @@ -1976,13 +1984,13 @@ void SurfaceFlinger::rebuildLayerStacks() { } else { // Clear out the HWC layer if this layer was // previously visible, but no longer is - hwcLayerDestroyed = layer->destroyHwcLayer(display->getId()); + hwcLayerDestroyed = displayId && layer->destroyHwcLayer(*displayId); } } else { // WM changes display->layerStack upon sleep/awake. // Here we make sure we delete the HWC layers even if // WM changed their layer stack. - hwcLayerDestroyed = layer->destroyHwcLayer(display->getId()); + hwcLayerDestroyed = displayId && layer->destroyHwcLayer(*displayId); } // If a layer is not going to get a release fence because @@ -2107,12 +2115,11 @@ void SurfaceFlinger::beginFrame(const sp& display) // emit any black frames until a layer is added to the layer stack. bool mustRecompose = dirty && !(empty && wasEmpty); - ALOGV_IF(display->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL, - "id[%d]: %s composition (%sdirty %sempty %swasEmpty)", display->getId(), - mustRecompose ? "doing" : "skipping", - dirty ? "+" : "-", - empty ? "+" : "-", - wasEmpty ? "+" : "-"); + const char flagPrefix[] = {'-', '+'}; + static_cast(flagPrefix); + ALOGV_IF(display->isVirtual(), "%s: %s composition for %s (%cdirty %cempty %cwasEmpty)", + __FUNCTION__, mustRecompose ? "doing" : "skipping", display->getDebugName().c_str(), + flagPrefix[dirty], flagPrefix[empty], flagPrefix[wasEmpty]); display->beginFrame(mustRecompose); @@ -2129,10 +2136,8 @@ void SurfaceFlinger::prepareFrame(const sp& display) status_t result = display->prepareFrame(getHwComposer(), getBE().mCompositionInfo[display->getDisplayToken()]); - ALOGE_IF(result != NO_ERROR, - "prepareFrame for display %d failed:" - " %d (%s)", - display->getId(), result, strerror(-result)); + ALOGE_IF(result != NO_ERROR, "prepareFrame failed for %s: %d (%s)", + display->getDebugName().c_str(), result, strerror(-result)); } void SurfaceFlinger::doComposition(const sp& display, bool repaintEverything) { @@ -2155,8 +2160,9 @@ void SurfaceFlinger::doComposition(const sp& display, bool repain void SurfaceFlinger::postFrame() { // |mStateLock| not needed as we are on the main thread - if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY)) { - uint32_t flipCount = getDefaultDisplayDeviceLocked()->getPageFlipCount(); + const auto display = getDefaultDisplayDeviceLocked(); + if (display && getHwComposer().isConnected(*display->getId())) { + uint32_t flipCount = display->getPageFlipCount(); if (flipCount % LOG_FRAME_STATS_PERIOD == 0) { logFrameStats(); } @@ -2172,8 +2178,8 @@ void SurfaceFlinger::postFramebuffer(const sp& display) if (display->isPoweredOn()) { const auto displayId = display->getId(); - if (displayId >= 0) { - getBE().mHwc->presentAndGetReleaseFences(displayId); + if (displayId) { + getHwComposer().presentAndGetReleaseFences(*displayId); } display->onSwapBuffersCompleted(); display->makeCurrent(); @@ -2183,9 +2189,9 @@ void SurfaceFlinger::postFramebuffer(const sp& display) // The layer buffer from the previous frame (if any) is released // by HWC only when the release fence from this frame (if any) is // signaled. Always get the release fence from HWC first. - auto hwcLayer = layer->getHwcLayer(displayId); - if (displayId >= 0) { - releaseFence = getBE().mHwc->getLayerReleaseFence(displayId, hwcLayer); + if (displayId && layer->hasHwcLayer(*displayId)) { + releaseFence = getHwComposer().getLayerReleaseFence(*displayId, + layer->getHwcLayer(*displayId)); } // If the layer was client composited in the previous frame, we @@ -2205,14 +2211,15 @@ void SurfaceFlinger::postFramebuffer(const sp& display) // display->getVisibleLayersSortedByZ. The best we can do is to // supply them with the present fence. if (!display->getLayersNeedingFences().isEmpty()) { - sp presentFence = getBE().mHwc->getPresentFence(displayId); + sp presentFence = + displayId ? getBE().mHwc->getPresentFence(*displayId) : Fence::NO_FENCE; for (auto& layer : display->getLayersNeedingFences()) { layer->getBE().onLayerDisplayed(presentFence); } } - if (displayId >= 0) { - getBE().mHwc->clearReleaseFences(displayId); + if (displayId) { + getHwComposer().clearReleaseFences(*displayId); } } } @@ -2247,72 +2254,36 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) // here the transaction has been committed } -DisplayDevice::DisplayType SurfaceFlinger::determineDisplayType(hwc2_display_t hwcDisplayId, - HWC2::Connection connection) const { - // Figure out whether the event is for the primary display or an - // external display by matching the Hwc display id against one for a - // connected display. If we did not find a match, we then check what - // displays are not already connected to determine the type. If we don't - // have a connected primary display, we assume the new display is meant to - // be the primary display, and then if we don't have an external display, - // we assume it is that. - const auto primaryHwcDisplayId = getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_PRIMARY); - const auto externalHwcDisplayId = - getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_EXTERNAL); - if (primaryHwcDisplayId && primaryHwcDisplayId == hwcDisplayId) { - return DisplayDevice::DISPLAY_PRIMARY; - } else if (externalHwcDisplayId && externalHwcDisplayId == hwcDisplayId) { - return DisplayDevice::DISPLAY_EXTERNAL; - } else if (connection == HWC2::Connection::Connected && !primaryHwcDisplayId) { - return DisplayDevice::DISPLAY_PRIMARY; - } else if (connection == HWC2::Connection::Connected && !externalHwcDisplayId) { - return DisplayDevice::DISPLAY_EXTERNAL; - } - - return DisplayDevice::DISPLAY_ID_INVALID; -} - void SurfaceFlinger::processDisplayHotplugEventsLocked() { for (const auto& event : mPendingHotplugEvents) { - auto displayType = determineDisplayType(event.hwcDisplayId, event.connection); - if (displayType == DisplayDevice::DISPLAY_ID_INVALID) { - ALOGW("Unable to determine the display type for display %" PRIu64, event.hwcDisplayId); - continue; - } + const std::optional info = + getHwComposer().onHotplug(event.hwcDisplayId, event.connection); - if (getBE().mHwc->isUsingVrComposer() && displayType == DisplayDevice::DISPLAY_EXTERNAL) { - ALOGE("External displays are not supported by the vr hardware composer."); + if (!info) { continue; } - const auto displayId = - getBE().mHwc->onHotplug(event.hwcDisplayId, displayType, event.connection); - if (displayId) { - ALOGV("Display %" PRIu64 " has stable ID %" PRIu64, event.hwcDisplayId, *displayId); - } - if (event.connection == HWC2::Connection::Connected) { - if (!mDisplayTokens[displayType].get()) { - ALOGV("Creating built in display %d", displayType); - mDisplayTokens[displayType] = new BBinder(); - DisplayDeviceState info; - info.type = displayType; - info.displayName = displayType == DisplayDevice::DISPLAY_PRIMARY ? - "Built-in Screen" : "External Screen"; - info.isSecure = true; // All physical displays are currently considered secure. - mCurrentState.displays.add(mDisplayTokens[displayType], info); - mInterceptor->saveDisplayCreation(info); + if (!mPhysicalDisplayTokens.count(info->id)) { + ALOGV("Creating display %" PRIu64, info->id); + mPhysicalDisplayTokens[info->id] = new BBinder(); + DisplayDeviceState state; + state.displayId = info->id; + state.isSecure = true; // All physical displays are currently considered secure. + state.displayName = info->name; + mCurrentState.displays.add(mPhysicalDisplayTokens[info->id], state); + mInterceptor->saveDisplayCreation(state); } } else { - ALOGV("Removing built in display %d", displayType); + ALOGV("Removing display %" PRIu64, info->id); - ssize_t idx = mCurrentState.displays.indexOfKey(mDisplayTokens[displayType]); - if (idx >= 0) { - const DisplayDeviceState& info(mCurrentState.displays.valueAt(idx)); - mInterceptor->saveDisplayDeletion(info.sequenceId); - mCurrentState.displays.removeItemsAt(idx); + ssize_t index = mCurrentState.displays.indexOfKey(mPhysicalDisplayTokens[info->id]); + if (index >= 0) { + const DisplayDeviceState& state = mCurrentState.displays.valueAt(index); + mInterceptor->saveDisplayDeletion(state.sequenceId); + mCurrentState.displays.removeItemsAt(index); } - mDisplayTokens[displayType].clear(); + mPhysicalDisplayTokens.erase(info->id); } processDisplayChangesLocked(); @@ -2322,31 +2293,36 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { } sp SurfaceFlinger::setupNewDisplayDeviceInternal( - const wp& displayToken, int32_t displayId, const DisplayDeviceState& state, - const sp& dispSurface, const sp& producer) { - DisplayDeviceCreationArgs creationArgs(this, displayToken, state.type, displayId); + const wp& displayToken, const std::optional& displayId, + const DisplayDeviceState& state, const sp& dispSurface, + const sp& producer) { + DisplayDeviceCreationArgs creationArgs(this, displayToken, displayId); + creationArgs.isVirtual = state.isVirtual(); creationArgs.isSecure = state.isSecure; creationArgs.displaySurface = dispSurface; creationArgs.hasWideColorGamut = false; creationArgs.supportedPerFrameMetadata = 0; - if (useColorManagement && displayId >= 0) { - std::vector modes = getHwComposer().getColorModes(displayId); + const bool isInternalDisplay = displayId && displayId == getInternalDisplayId(); + creationArgs.isPrimary = isInternalDisplay; + + if (useColorManagement && displayId) { + std::vector modes = getHwComposer().getColorModes(*displayId); for (ColorMode colorMode : modes) { if (isWideColorMode(colorMode)) { creationArgs.hasWideColorGamut = true; } std::vector renderIntents = - getHwComposer().getRenderIntents(displayId, colorMode); + getHwComposer().getRenderIntents(*displayId, colorMode); creationArgs.hwcColorModes.emplace(colorMode, renderIntents); } } - if (displayId >= 0) { - getHwComposer().getHdrCapabilities(displayId, &creationArgs.hdrCapabilities); + if (displayId) { + getHwComposer().getHdrCapabilities(*displayId, &creationArgs.hdrCapabilities); creationArgs.supportedPerFrameMetadata = - getHwComposer().getSupportedPerFrameMetadata(displayId); + getHwComposer().getSupportedPerFrameMetadata(*displayId); } auto nativeWindowSurface = getFactory().createNativeWindowSurface(producer); @@ -2357,7 +2333,7 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( * Create our display's surface */ std::unique_ptr renderSurface = getRenderEngine().createSurface(); - renderSurface->setCritical(state.type == DisplayDevice::DISPLAY_PRIMARY); + renderSurface->setCritical(isInternalDisplay); renderSurface->setAsync(state.isVirtual()); renderSurface->setNativeWindow(nativeWindow.get()); creationArgs.displayWidth = renderSurface->getWidth(); @@ -2375,9 +2351,8 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( nativeWindow->setSwapInterval(nativeWindow.get(), 0); } - creationArgs.displayInstallOrientation = state.type == DisplayDevice::DISPLAY_PRIMARY - ? primaryDisplayOrientation - : DisplayState::eOrientationDefault; + creationArgs.displayInstallOrientation = + isInternalDisplay ? primaryDisplayOrientation : DisplayState::eOrientationDefault; // virtual displays are always considered enabled creationArgs.initialPowerMode = state.isVirtual() ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF; @@ -2396,9 +2371,11 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( } setActiveColorModeInternal(display, defaultColorMode, defaultDataSpace, RenderIntent::COLORIMETRIC); - if (state.type < DisplayDevice::DISPLAY_VIRTUAL) { - display->setActiveConfig(getHwComposer().getActiveConfigIndex(state.type)); + if (!state.isVirtual()) { + LOG_ALWAYS_FATAL_IF(!displayId); + display->setActiveConfig(getHwComposer().getActiveConfigIndex(*displayId)); } + display->setLayerStack(state.layerStack); display->setProjection(state.orientation, state.viewport, state.frame); display->setDisplayName(state.displayName); @@ -2424,6 +2401,10 @@ void SurfaceFlinger::processDisplayChangesLocked() { for (size_t i = 0; i < dc;) { const ssize_t j = curr.indexOfKey(draw.keyAt(i)); if (j < 0) { + // Save display IDs before disconnecting. + const auto internalDisplayId = getInternalDisplayId(); + const auto externalDisplayId = getExternalDisplayId(); + // in drawing state but not in current state // Call makeCurrent() on the primary display so we can // be sure that nothing associated with this display @@ -2434,14 +2415,14 @@ void SurfaceFlinger::processDisplayChangesLocked() { if (const auto display = getDisplayDeviceLocked(draw.keyAt(i))) { display->disconnect(getHwComposer()); } - if (draw[i].type == DisplayDevice::DISPLAY_PRIMARY) { + if (internalDisplayId && internalDisplayId == draw[i].displayId) { if (mUseScheduler) { mScheduler->hotplugReceived(mAppConnectionHandle, EventThread::DisplayType::Primary, false); } else { mEventThread->onHotplugReceived(EventThread::DisplayType::Primary, false); } - } else if (draw[i].type == DisplayDevice::DISPLAY_EXTERNAL) { + } else if (externalDisplayId && externalDisplayId == draw[i].displayId) { if (mUseScheduler) { mScheduler->hotplugReceived(mAppConnectionHandle, EventThread::DisplayType::External, false); @@ -2499,14 +2480,14 @@ void SurfaceFlinger::processDisplayChangesLocked() { sp bqConsumer; getFactory().createBufferQueue(&bqProducer, &bqConsumer, false); - int32_t displayId = -1; + std::optional displayId; if (state.isVirtual()) { // Virtual displays without a surface are dormant: // they have external state (layer stack, projection, // etc.) but no internal state (i.e. a DisplayDevice). if (state.surface != nullptr) { // Allow VR composer to use virtual displays. - if (mUseHwcVirtualDisplays || getBE().mHwc->isUsingVrComposer()) { + if (mUseHwcVirtualDisplays || getHwComposer().isUsingVrComposer()) { int width = 0; int status = state.surface->query(NATIVE_WINDOW_WIDTH, &width); ALOGE_IF(status != NO_ERROR, "Unable to query width (%d)", status); @@ -2518,14 +2499,14 @@ void SurfaceFlinger::processDisplayChangesLocked() { ALOGE_IF(status != NO_ERROR, "Unable to query format (%d)", status); auto format = static_cast(intFormat); - getBE().mHwc->allocateVirtualDisplay(width, height, &format, - &displayId); + displayId = + getHwComposer().allocateVirtualDisplay(width, height, &format); } // TODO: Plumb requested format back up to consumer sp vds = - new VirtualDisplaySurface(*getBE().mHwc, displayId, state.surface, + new VirtualDisplaySurface(getHwComposer(), displayId, state.surface, bqProducer, bqConsumer, state.displayName); @@ -2538,8 +2519,9 @@ void SurfaceFlinger::processDisplayChangesLocked() { "surface is provided (%p), ignoring it", state.surface.get()); - displayId = state.type; - dispSurface = new FramebufferSurface(*getBE().mHwc, displayId, bqConsumer); + displayId = state.displayId; + LOG_ALWAYS_FATAL_IF(!displayId); + dispSurface = new FramebufferSurface(getHwComposer(), *displayId, bqConsumer); producer = bqProducer; } @@ -2549,7 +2531,9 @@ void SurfaceFlinger::processDisplayChangesLocked() { setupNewDisplayDeviceInternal(displayToken, displayId, state, dispSurface, producer)); if (!state.isVirtual()) { - if (state.type == DisplayDevice::DISPLAY_PRIMARY) { + LOG_ALWAYS_FATAL_IF(!displayId); + + if (displayId == getInternalDisplayId()) { if (mUseScheduler) { mScheduler->hotplugReceived(mAppConnectionHandle, EventThread::DisplayType::Primary, @@ -2558,7 +2542,7 @@ void SurfaceFlinger::processDisplayChangesLocked() { mEventThread->onHotplugReceived(EventThread::DisplayType::Primary, true); } - } else if (state.type == DisplayDevice::DISPLAY_EXTERNAL) { + } else if (displayId == getExternalDisplayId()) { if (mUseScheduler) { mScheduler->hotplugReceived(mAppConnectionHandle, EventThread::DisplayType::External, @@ -2712,7 +2696,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) void SurfaceFlinger::updateCursorAsync() { for (const auto& [token, display] : mDisplays) { - if (display->getId() < 0) { + if (!display->getId()) { continue; } @@ -3104,8 +3088,9 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& display) { case HWC2::Composition::Device: case HWC2::Composition::Sideband: case HWC2::Composition::SolidColor: { + LOG_ALWAYS_FATAL_IF(!displayId); const Layer::State& state(layer->getDrawingState()); - if (layer->getClearClientTarget(displayId) && !firstLayer && + if (layer->getClearClientTarget(*displayId) && !firstLayer && layer->isOpaque(state) && (layer->getAlpha() == 1.0f) && hasClientComposition) { // never clear the very first layer since we're @@ -3806,7 +3791,7 @@ void SurfaceFlinger::onHandleDestroyed(const sp& layer) // --------------------------------------------------------------------------- void SurfaceFlinger::onInitializeDisplays() { - const auto displayToken = mDisplayTokens[DisplayDevice::DISPLAY_PRIMARY]; + const auto displayToken = getInternalDisplayToken(); if (!displayToken) return; // reset screen orientation and use primary layer stack @@ -3830,7 +3815,7 @@ void SurfaceFlinger::onInitializeDisplays() { setPowerModeInternal(display, HWC_POWER_MODE_NORMAL, /*stateLockHeld*/ false); - const auto activeConfig = getHwComposer().getActiveConfig(display->getId()); + const auto activeConfig = getHwComposer().getActiveConfig(*display->getId()); const nsecs_t period = activeConfig->getVsyncPeriod(); mAnimFrameTracker.setDisplayRefreshPeriod(period); @@ -3847,16 +3832,18 @@ void SurfaceFlinger::initializeDisplays() { void SurfaceFlinger::setPowerModeInternal(const sp& display, int mode, bool stateLockHeld) { - const int32_t displayId = display->getId(); - ALOGD("Setting power mode %d on display %d", mode, displayId); - - int currentMode = display->getPowerMode(); - if (mode == currentMode) { + if (display->isVirtual()) { + ALOGE("%s: Invalid operation on virtual display", __FUNCTION__); return; } - if (display->isVirtual()) { - ALOGW("Trying to set power mode for virtual display"); + const auto displayId = display->getId(); + LOG_ALWAYS_FATAL_IF(!displayId); + + ALOGD("Setting power mode %d on display %" PRIu64, mode, *displayId); + + int currentMode = display->getPowerMode(); + if (mode == currentMode) { return; } @@ -3872,12 +3859,10 @@ void SurfaceFlinger::setPowerModeInternal(const sp& display, int mInterceptor->savePowerModeUpdate(mCurrentState.displays.valueAt(idx).sequenceId, mode); } - int32_t type = display->getDisplayType(); if (currentMode == HWC_POWER_MODE_OFF) { // Turn on the display - getHwComposer().setPowerMode(type, mode); + getHwComposer().setPowerMode(*displayId, mode); if (display->isPrimary() && mode != HWC_POWER_MODE_DOZE_SUSPEND) { - // FIXME: eventthread only knows about the main display right now if (mUseScheduler) { mScheduler->onScreenAcquired(mAppConnectionHandle); } else { @@ -3908,7 +3893,6 @@ void SurfaceFlinger::setPowerModeInternal(const sp& display, int } else { disableHardwareVsync(true); // also cancels any in-progress resync } - // FIXME: eventthread only knows about the main display right now if (mUseScheduler) { mScheduler->onScreenReleased(mAppConnectionHandle); } else { @@ -3916,15 +3900,14 @@ void SurfaceFlinger::setPowerModeInternal(const sp& display, int } } - getHwComposer().setPowerMode(type, mode); + getHwComposer().setPowerMode(*displayId, mode); mVisibleRegionsDirty = true; // from this point on, SF will stop drawing on this display } else if (mode == HWC_POWER_MODE_DOZE || mode == HWC_POWER_MODE_NORMAL) { // Update display while dozing - getHwComposer().setPowerMode(type, mode); + getHwComposer().setPowerMode(*displayId, mode); if (display->isPrimary() && currentMode == HWC_POWER_MODE_DOZE_SUSPEND) { - // FIXME: eventthread only knows about the main display right now if (mUseScheduler) { mScheduler->onScreenAcquired(mAppConnectionHandle); } else { @@ -3940,24 +3923,23 @@ void SurfaceFlinger::setPowerModeInternal(const sp& display, int } else { disableHardwareVsync(true); // also cancels any in-progress resync } - // FIXME: eventthread only knows about the main display right now if (mUseScheduler) { mScheduler->onScreenReleased(mAppConnectionHandle); } else { mEventThread->onScreenReleased(); } } - getHwComposer().setPowerMode(type, mode); + getHwComposer().setPowerMode(*displayId, mode); } else { ALOGE("Attempting to set unknown power mode: %d\n", mode); - getHwComposer().setPowerMode(type, mode); + getHwComposer().setPowerMode(*displayId, mode); } if (display->isPrimary()) { mTimeStats.setPowerMode(mode); } - ALOGD("Finished setting power mode %d on display %d", mode, displayId); + ALOGD("Finished setting power mode %d on display %" PRIu64, mode, *displayId); } void SurfaceFlinger::setPowerMode(const sp& displayToken, int mode) { @@ -4136,9 +4118,9 @@ void SurfaceFlinger::dumpStatsLocked(const Vector& args, size_t& index index++; } - if (const auto displayId = DisplayDevice::DISPLAY_PRIMARY; - getHwComposer().isConnected(displayId)) { - const auto activeConfig = getBE().mHwc->getActiveConfig(displayId); + if (const auto displayId = getInternalDisplayId(); + displayId && getHwComposer().isConnected(*displayId)) { + const auto activeConfig = getHwComposer().getActiveConfig(*displayId); const nsecs_t period = activeConfig->getVsyncPeriod(); result.appendFormat("%" PRId64 "\n", period); } @@ -4279,13 +4261,17 @@ void SurfaceFlinger::dumpBufferingStats(String8& result) const { void SurfaceFlinger::dumpDisplayIdentificationData(String8& result) const { for (const auto& [token, display] : mDisplays) { - const int32_t displayId = display->getId(); - const auto hwcDisplayId = getHwComposer().getHwcDisplayId(displayId); + const auto displayId = display->getId(); + if (!displayId) { + continue; + } + const auto hwcDisplayId = getHwComposer().fromPhysicalDisplayId(*displayId); if (!hwcDisplayId) { continue; } - result.appendFormat("Display %d (HWC display %" PRIu64 "): ", displayId, *hwcDisplayId); + result.appendFormat("Display %" PRIu64 " (HWC display %" PRIu64 "): ", *displayId, + *hwcDisplayId); uint8_t port; DisplayIdentificationData data; if (!getHwComposer().getDisplayIdentificationData(*hwcDisplayId, &port, &data)) { @@ -4316,7 +4302,6 @@ void SurfaceFlinger::dumpDisplayIdentificationData(String8& result) const { result.append(edid->displayName.data(), edid->displayName.length()); result.append("\"\n"); } - result.append("\n"); } void SurfaceFlinger::dumpWideColorInfo(String8& result) const { @@ -4328,13 +4313,13 @@ void SurfaceFlinger::dumpWideColorInfo(String8& result) const { // TODO: print out if wide-color mode is active or not for (const auto& [token, display] : mDisplays) { - const int32_t displayId = display->getId(); - if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { + const auto displayId = display->getId(); + if (!displayId) { continue; } - result.appendFormat("Display %d color modes:\n", displayId); - std::vector modes = getHwComposer().getColorModes(displayId); + result.appendFormat("Display %" PRIu64 " color modes:\n", *displayId); + std::vector modes = getHwComposer().getColorModes(*displayId); for (auto&& mode : modes) { result.appendFormat(" %s (%d)\n", decodeColorMode(mode).c_str(), mode); } @@ -4390,11 +4375,12 @@ LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(const DisplayDevice& disp layersProto.set_color_transform(decodeColorTransform(display.getColorTransform())); layersProto.set_global_transform(static_cast(display.getOrientationTransform())); - const int32_t displayId = display.getId(); + const auto displayId = display.getId(); + LOG_ALWAYS_FATAL_IF(!displayId); mDrawingState.traverseInZOrder([&](Layer* layer) { - if (!layer->visibleRegion.isEmpty() && layer->getBE().mHwcLayers.count(displayId)) { + if (!layer->visibleRegion.isEmpty() && layer->getBE().mHwcLayers.count(*displayId)) { LayerProto* layerProto = layersProto.add_layers(); - layer->writeToProto(layerProto, displayId); + layer->writeToProto(layerProto, *displayId); } }); @@ -4448,25 +4434,19 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, const auto [sfEarlyOffset, appEarlyOffset] = mVsyncModulator.getEarlyOffsets(); const auto [sfEarlyGlOffset, appEarlyGlOffset] = mVsyncModulator.getEarlyGlOffsets(); - if (const auto displayId = DisplayDevice::DISPLAY_PRIMARY; - getHwComposer().isConnected(displayId)) { - const auto activeConfig = getHwComposer().getActiveConfig(displayId); - result.appendFormat("Display %d: " - "app phase %" PRId64 " ns, " - "sf phase %" PRId64 " ns, " - "early app phase %" PRId64 " ns, " - "early sf phase %" PRId64 " ns, " - "early app gl phase %" PRId64 " ns, " - "early sf gl phase %" PRId64 " ns, " - "present offset %" PRId64 " ns (refresh %" PRId64 " ns)", - displayId, - vsyncPhaseOffsetNs, - sfVsyncPhaseOffsetNs, - appEarlyOffset, - sfEarlyOffset, - appEarlyGlOffset, - sfEarlyGlOffset, - dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod()); + if (const auto displayId = getInternalDisplayId(); + displayId && getHwComposer().isConnected(*displayId)) { + const auto activeConfig = getHwComposer().getActiveConfig(*displayId); + result.appendFormat("Display %" PRIu64 ": app phase %" PRId64 " ns, " + "sf phase %" PRId64 " ns, " + "early app phase %" PRId64 " ns, " + "early sf phase %" PRId64 " ns, " + "early app gl phase %" PRId64 " ns, " + "early sf gl phase %" PRId64 " ns, " + "present offset %" PRId64 " ns (refresh %" PRId64 " ns)", + *displayId, vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, appEarlyOffset, + sfEarlyOffset, appEarlyGlOffset, sfEarlyGlOffset, + dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod()); } result.append("\n"); @@ -4519,12 +4499,9 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, result.append("SurfaceFlinger global state:\n"); colorizer.reset(result); - HWComposer& hwc(getHwComposer()); - const auto display = getDefaultDisplayDeviceLocked(); - getBE().mRenderEngine->dump(result); - if (display) { + if (const auto display = getDefaultDisplayDeviceLocked()) { display->undefinedRegion.dump(result, "undefinedRegion"); result.appendFormat(" orientation=%d, isPoweredOn=%d\n", display->getOrientation(), display->isPoweredOn()); @@ -4533,8 +4510,9 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, " gpu_to_cpu_unsupported : %d\n", mTransactionFlags.load(), !mGpuToCpuSupported); - if (display) { - const auto activeConfig = getHwComposer().getActiveConfig(display->getId()); + if (const auto displayId = getInternalDisplayId(); + displayId && getHwComposer().isConnected(*displayId)) { + const auto activeConfig = getHwComposer().getActiveConfig(*displayId); result.appendFormat(" refresh-rate : %f fps\n" " x-dpi : %f\n" " y-dpi : %f\n", @@ -4566,14 +4544,14 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, * HWC layer minidump */ for (const auto& [token, display] : mDisplays) { - const int32_t displayId = display->getId(); - if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { + const auto displayId = display->getId(); + if (!displayId) { continue; } - result.appendFormat("Display %d HWC layers:\n", displayId); + result.appendFormat("Display %" PRIu64 " HWC layers:\n", *displayId); Layer::miniDumpHeader(result); - mCurrentState.traverseInZOrder([&](Layer* layer) { layer->miniDump(result, displayId); }); + mCurrentState.traverseInZOrder([&](Layer* layer) { layer->miniDump(result, *displayId); }); result.append("\n"); } @@ -4586,7 +4564,7 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, bool hwcDisabled = mDebugDisableHWC || mDebugRegion; result.appendFormat(" h/w composer %s\n", hwcDisabled ? "disabled" : "enabled"); - hwc.dump(result); + getHwComposer().dump(result); /* * Dump gralloc state @@ -4604,7 +4582,7 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, } } -const Vector>& SurfaceFlinger::getLayerSortedByZForHwcDisplay(int32_t displayId) { +const Vector>& SurfaceFlinger::getLayerSortedByZForHwcDisplay(DisplayId displayId) { // Note: mStateLock is held here for (const auto& [token, display] : mDisplays) { if (display->getId() == displayId) { @@ -4612,7 +4590,7 @@ const Vector>& SurfaceFlinger::getLayerSortedByZForHwcDisplay(int32_t } } - ALOGE("%s: Invalid display %d", __FUNCTION__, displayId); + ALOGE("%s: Invalid display %" PRIu64, __FUNCTION__, displayId); static const Vector> empty; return empty; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 51168a6724..36bb62c080 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -76,10 +76,11 @@ #include #include #include +#include #include #include +#include #include -#include "RenderArea.h" #include @@ -348,7 +349,7 @@ public: // enable/disable h/w composer event // TODO: this should be made accessible only to EventThread - void setVsyncEnabled(int disp, int enabled); + void setVsyncEnabled(EventThread::DisplayType displayType, bool enabled); // called on the main thread by MessageQueue when an internal message // is received @@ -357,7 +358,7 @@ public: // for debugging only // TODO: this should be made accessible only to HWComposer - const Vector< sp >& getLayerSortedByZForHwcDisplay(int id); + const Vector>& getLayerSortedByZForHwcDisplay(DisplayId displayId); renderengine::RenderEngine& getRenderEngine() const { return *getBE().mRenderEngine; } @@ -659,7 +660,10 @@ private: } sp getDefaultDisplayDeviceLocked() { - return getDisplayDeviceLocked(mDisplayTokens[DisplayDevice::DISPLAY_PRIMARY]); + if (const auto token = getInternalDisplayToken()) { + return getDisplayDeviceLocked(token); + } + return nullptr; } // mark a region of a layer stack dirty. this updates the dirty @@ -724,10 +728,8 @@ private: /* ------------------------------------------------------------------------ * Display management */ - DisplayDevice::DisplayType determineDisplayType(hwc2_display_t hwcDisplayId, - HWC2::Connection connection) const; sp setupNewDisplayDeviceInternal(const wp& displayToken, - int32_t displayId, + const std::optional& displayId, const DisplayDeviceState& state, const sp& dispSurface, const sp& producer); @@ -759,6 +761,37 @@ public: } private: + sp getPhysicalDisplayToken(DisplayId displayId) const { + const auto it = mPhysicalDisplayTokens.find(displayId); + return it != mPhysicalDisplayTokens.end() ? it->second : nullptr; + } + + std::optional getPhysicalDisplayId(const sp& displayToken) const { + for (const auto& [id, token] : mPhysicalDisplayTokens) { + if (token == displayToken) { + return id; + } + } + return {}; + } + + // TODO(b/74619554): Remove special cases for primary display. + sp getInternalDisplayToken() const { + const auto displayId = getInternalDisplayId(); + return displayId ? getPhysicalDisplayToken(*displayId) : nullptr; + } + + std::optional getInternalDisplayId() const { + const auto hwcDisplayId = getHwComposer().getInternalHwcDisplayId(); + return hwcDisplayId ? getHwComposer().toPhysicalDisplayId(*hwcDisplayId) : std::nullopt; + } + + // TODO(b/74619554): Remove special cases for external display. + std::optional getExternalDisplayId() const { + const auto hwcDisplayId = getHwComposer().getExternalHwcDisplayId(); + return hwcDisplayId ? getHwComposer().toPhysicalDisplayId(*hwcDisplayId) : std::nullopt; + } + void listLayersLocked(const Vector& args, size_t& index, String8& result) const; void dumpStatsLocked(const Vector& args, size_t& index, String8& result) const; void clearStatsLocked(const Vector& args, size_t& index, String8& result); @@ -836,7 +869,7 @@ private: std::unique_ptr mSfEventThreadSource; std::unique_ptr mVSyncInjector; std::unique_ptr mEventControlThread; - sp mDisplayTokens[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES]; + std::unordered_map> mPhysicalDisplayTokens; VSyncModulator mVsyncModulator; diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 57bda5a8c9..7faaff6ea6 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -495,8 +495,10 @@ void SurfaceInterceptor::addDisplayCreationLocked(Increment* increment, DisplayCreation* creation(increment->mutable_display_creation()); creation->set_id(info.sequenceId); creation->set_name(info.displayName); - creation->set_type(info.type); creation->set_is_secure(info.isSecure); + if (info.displayId) { + creation->set_display_id(*info.displayId); + } } void SurfaceInterceptor::addDisplayDeletionLocked(Increment* increment, int32_t sequenceId) { diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index f1a8842b1d..09bb8c58f6 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -65,6 +65,7 @@ constexpr hwc2_display_t HWC_DISPLAY = FakeHwcDisplayInjector::DEFAULT_HWC_DISPL constexpr hwc2_layer_t HWC_LAYER = 5000; constexpr Transform DEFAULT_TRANSFORM = static_cast(0); +constexpr DisplayId DEFAULT_DISPLAY_ID = 42; constexpr int DEFAULT_DISPLAY_WIDTH = 1920; constexpr int DEFAULT_DISPLAY_HEIGHT = 1024; @@ -226,12 +227,13 @@ struct BaseDisplayVariant { static constexpr int INIT_POWER_MODE = HWC_POWER_MODE_NORMAL; static void setupPreconditions(CompositionTest* test) { - FakeHwcDisplayInjector(DisplayDevice::DISPLAY_PRIMARY, HWC2::DisplayType::Physical) + FakeHwcDisplayInjector(DEFAULT_DISPLAY_ID, HWC2::DisplayType::Physical, + true /* isPrimary */) .setCapabilities(&test->mDefaultCapabilities) .inject(&test->mFlinger, test->mComposer); - test->mDisplay = FakeDisplayDeviceInjector(test->mFlinger, DisplayDevice::DISPLAY_PRIMARY, - DisplayDevice::DISPLAY_PRIMARY) + test->mDisplay = FakeDisplayDeviceInjector(test->mFlinger, DEFAULT_DISPLAY_ID, + false /* isVirtual */, true /* isPrimary */) .setDisplaySize(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT) .setDisplaySurface(test->mDisplaySurface) .setRenderSurface(std::unique_ptr( @@ -745,7 +747,9 @@ struct BaseLayerVariant { EXPECT_CALL(*test->mComposer, createLayer(HWC_DISPLAY, _)) .WillOnce(DoAll(SetArgPointee<1>(HWC_LAYER), Return(Error::NONE))); - layer->createHwcLayer(test->mFlinger.mFlinger->getBE().mHwc.get(), test->mDisplay->getId()); + const auto displayId = test->mDisplay->getId(); + ASSERT_TRUE(displayId); + layer->createHwcLayer(test->mFlinger.mFlinger->getBE().mHwc.get(), *displayId); Mock::VerifyAndClear(test->mComposer); @@ -758,8 +762,10 @@ struct BaseLayerVariant { static void cleanupInjectedLayers(CompositionTest* test) { EXPECT_CALL(*test->mComposer, destroyLayer(HWC_DISPLAY, HWC_LAYER)) .WillOnce(Return(Error::NONE)); + const auto displayId = test->mDisplay->getId(); + ASSERT_TRUE(displayId); for (auto layer : test->mFlinger.mutableDrawingState().layersSortedByZ) { - layer->destroyHwcLayer(test->mDisplay->getId()); + layer->destroyHwcLayer(*displayId); } test->mFlinger.mutableDrawingState().layersSortedByZ.clear(); } @@ -947,7 +953,7 @@ struct RECompositionResultVariant : public CompositionResultBaseVariant { struct ForcedClientCompositionResultVariant : public RECompositionResultVariant { static void setupLayerState(CompositionTest*, sp layer) { - layer->forceClientComposition(DisplayDevice::DISPLAY_PRIMARY); + layer->forceClientComposition(DEFAULT_DISPLAY_ID); } template diff --git a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp index 4f1c99e417..55995d048a 100644 --- a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp @@ -68,32 +68,44 @@ DisplayIdentificationData asDisplayIdentificationData(const unsigned char (&byte } // namespace +const DisplayIdentificationData& getInternalEdid() { + static const DisplayIdentificationData data = asDisplayIdentificationData(kInternalEdid); + return data; +} + +const DisplayIdentificationData& getExternalEdid() { + static const DisplayIdentificationData data = asDisplayIdentificationData(kExternalEdid); + return data; +} + +const DisplayIdentificationData& getExternalEedid() { + static const DisplayIdentificationData data = asDisplayIdentificationData(kExternalEedid); + return data; +} + TEST(DisplayIdentificationTest, isEdid) { EXPECT_FALSE(isEdid({})); - EXPECT_TRUE(isEdid(asDisplayIdentificationData(kInternalEdid))); - EXPECT_TRUE(isEdid(asDisplayIdentificationData(kExternalEdid))); - EXPECT_TRUE(isEdid(asDisplayIdentificationData(kExternalEedid))); + EXPECT_TRUE(isEdid(getInternalEdid())); + EXPECT_TRUE(isEdid(getExternalEdid())); + EXPECT_TRUE(isEdid(getExternalEedid())); } TEST(DisplayIdentificationTest, parseEdid) { - auto data = asDisplayIdentificationData(kInternalEdid); - auto edid = parseEdid(data); + auto edid = parseEdid(getInternalEdid()); ASSERT_TRUE(edid); EXPECT_EQ(0x4ca3u, edid->manufacturerId); EXPECT_STREQ("SEC", edid->pnpId.data()); // ASCII text should be used as fallback if display name and serial number are missing. EXPECT_EQ("121AT11-801", edid->displayName); - data = asDisplayIdentificationData(kExternalEdid); - edid = parseEdid(data); + edid = parseEdid(getExternalEdid()); ASSERT_TRUE(edid); EXPECT_EQ(0x22f0u, edid->manufacturerId); EXPECT_STREQ("HWP", edid->pnpId.data()); EXPECT_EQ("HP ZR30w", edid->displayName); - data = asDisplayIdentificationData(kExternalEedid); - edid = parseEdid(data); + edid = parseEdid(getExternalEedid()); ASSERT_TRUE(edid); EXPECT_EQ(0x4c2du, edid->manufacturerId); EXPECT_STREQ("SAM", edid->pnpId.data()); @@ -105,7 +117,7 @@ TEST(DisplayIdentificationTest, parseInvalidEdid) { EXPECT_FALSE(parseEdid({})); // Display name must be printable. - auto data = asDisplayIdentificationData(kExternalEdid); + auto data = getExternalEdid(); data[97] = '\x1b'; auto edid = parseEdid(data); ASSERT_TRUE(edid); @@ -128,20 +140,32 @@ TEST(DisplayIdentificationTest, getPnpId) { EXPECT_STREQ("SAM", getPnpId(0x4c2du).value_or(PnpId{}).data()); } -TEST(DisplayIdentificationTest, generateDisplayId) { - const auto primaryId = generateDisplayId(0, asDisplayIdentificationData(kInternalEdid)); - ASSERT_TRUE(primaryId); +TEST(DisplayIdentificationTest, parseDisplayIdentificationData) { + const auto primaryInfo = parseDisplayIdentificationData(0, getInternalEdid()); + ASSERT_TRUE(primaryInfo); - const auto secondaryId = generateDisplayId(1, asDisplayIdentificationData(kExternalEdid)); - ASSERT_TRUE(secondaryId); + const auto secondaryInfo = parseDisplayIdentificationData(1, getExternalEdid()); + ASSERT_TRUE(secondaryInfo); - const auto tertiaryId = generateDisplayId(2, asDisplayIdentificationData(kExternalEedid)); - ASSERT_TRUE(tertiaryId); + const auto tertiaryInfo = parseDisplayIdentificationData(2, getExternalEedid()); + ASSERT_TRUE(tertiaryInfo); // Display IDs should be unique. - EXPECT_NE(primaryId, secondaryId); - EXPECT_NE(primaryId, tertiaryId); - EXPECT_NE(secondaryId, tertiaryId); + EXPECT_NE(primaryInfo->id, secondaryInfo->id); + EXPECT_NE(primaryInfo->id, tertiaryInfo->id); + EXPECT_NE(secondaryInfo->id, tertiaryInfo->id); +} + +TEST(DisplayIdentificationTest, getFallbackDisplayId) { + // Manufacturer ID should be invalid. + ASSERT_FALSE(getPnpId(getFallbackDisplayId(0))); + ASSERT_FALSE(getPnpId(getFallbackDisplayId(0xffu))); +} + +TEST(DisplayIdentificationTest, getVirtualDisplayId) { + // Manufacturer ID should be invalid. + ASSERT_FALSE(getPnpId(getVirtualDisplayId(0))); + ASSERT_FALSE(getPnpId(getVirtualDisplayId(0xffff'ffffu))); } } // namespace android diff --git a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.h b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.h new file mode 100644 index 0000000000..1c8e5cc9d3 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.h @@ -0,0 +1,27 @@ +/* + * Copyright 2018 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 "DisplayHardware/DisplayIdentification.h" + +namespace android { + +const DisplayIdentificationData& getInternalEdid(); +const DisplayIdentificationData& getExternalEdid(); +const DisplayIdentificationData& getExternalEedid(); + +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index d32627a7d3..2e90a59933 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -17,12 +17,16 @@ #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" +#include + #include #include #include #include + +#include "DisplayIdentificationTest.h" #include "TestableSurfaceFlinger.h" #include "mock/DisplayHardware/MockComposer.h" #include "mock/DisplayHardware/MockDisplaySurface.h" @@ -75,9 +79,11 @@ constexpr int HWC_POWER_MODE_LEET = 1337; // An out of range power mode value #define BOOL_SUBSTITUTE(TYPENAME) enum class TYPENAME : bool { FALSE = false, TRUE = true }; -BOOL_SUBSTITUTE(Critical); BOOL_SUBSTITUTE(Async); +BOOL_SUBSTITUTE(Critical); +BOOL_SUBSTITUTE(Primary); BOOL_SUBSTITUTE(Secure); +BOOL_SUBSTITUTE(Virtual); /* ------------------------------------------------------------------------ * @@ -98,7 +104,7 @@ public: // -------------------------------------------------------------------- // Postcondition helpers - bool hasHwcDisplay(hwc2_display_t displayId); + bool hasPhysicalHwcDisplay(hwc2_display_t hwcDisplayId); bool hasTransactionFlagSet(int flag); bool hasDisplayDevice(sp displayToken); sp getDisplayDevice(sp displayToken); @@ -204,8 +210,8 @@ void DisplayTransactionTest::injectFakeNativeWindowSurfaceFactory() { }); } -bool DisplayTransactionTest::hasHwcDisplay(hwc2_display_t displayId) { - return mFlinger.mutableHwcDisplaySlots().count(displayId) == 1; +bool DisplayTransactionTest::hasPhysicalHwcDisplay(hwc2_display_t hwcDisplayId) { + return mFlinger.mutableHwcPhysicalDisplayIdMap().count(hwcDisplayId) == 1; } bool DisplayTransactionTest::hasTransactionFlagSet(int flag) { @@ -240,20 +246,67 @@ const DisplayDeviceState& DisplayTransactionTest::getDrawingDisplayState(sp +template +struct PhysicalDisplayId {}; + +template +using VirtualDisplayId = std::integral_constant; + +struct NoDisplayId {}; + +template +struct IsPhysicalDisplayId : std::bool_constant {}; + +template +struct IsPhysicalDisplayId> : std::bool_constant {}; + +template +struct DisplayIdGetter; + +template +struct DisplayIdGetter> { + static std::optional get() { + if (!PhysicalDisplay::HAS_IDENTIFICATION_DATA) { + return getFallbackDisplayId(static_cast(PhysicalDisplay::PRIMARY) + ? HWC_DISPLAY_PRIMARY + : HWC_DISPLAY_EXTERNAL); + } + + const auto info = + parseDisplayIdentificationData(PhysicalDisplay::PORT, + PhysicalDisplay::GET_IDENTIFICATION_DATA()); + return info ? std::make_optional(info->id) : std::nullopt; + } +}; + +template +struct DisplayIdGetter> { + static std::optional get() { return displayId; } +}; + +template <> +struct DisplayIdGetter { + static std::optional get() { return {}; } +}; + +// DisplayIdType can be: +// 1) PhysicalDisplayId<...> for generated ID of physical display backed by HWC. +// 2) VirtualDisplayId<...> for hard-coded ID of virtual display backed by HWC. +// 3) NoDisplayId for virtual display without HWC backing. +template struct DisplayVariant { + using DISPLAY_ID = DisplayIdGetter; + // The display width and height static constexpr int WIDTH = width; static constexpr int HEIGHT = height; static constexpr int GRALLOC_USAGE = grallocUsage; - // The type for this display - static constexpr DisplayDevice::DisplayType TYPE = type; - static_assert(TYPE != DisplayDevice::DISPLAY_ID_INVALID); - - static constexpr DisplayDevice::DisplayType DISPLAY_ID = displayId; + // Whether the display is virtual or physical + static constexpr Virtual VIRTUAL = + IsPhysicalDisplayId{} ? Virtual::FALSE : Virtual::TRUE; // When creating native window surfaces for the framebuffer, whether those should be critical static constexpr Critical CRITICAL = critical; @@ -264,8 +317,14 @@ struct DisplayVariant { // Whether the display should be treated as secure static constexpr Secure SECURE = secure; + // Whether the display is primary + static constexpr Primary PRIMARY = primary; + static auto makeFakeExistingDisplayInjector(DisplayTransactionTest* test) { - auto injector = FakeDisplayDeviceInjector(test->mFlinger, TYPE, DISPLAY_ID); + auto injector = + FakeDisplayDeviceInjector(test->mFlinger, DISPLAY_ID::get(), + static_cast(VIRTUAL), static_cast(PRIMARY)); + injector.setSecure(static_cast(SECURE)); return injector; } @@ -306,7 +365,8 @@ struct DisplayVariant { } }; -template +template struct HwcDisplayVariant { // The display id supplied by the HWC static constexpr hwc2_display_t HWC_DISPLAY_ID = hwcDisplayId; @@ -325,7 +385,10 @@ struct HwcDisplayVariant { // Called by tests to inject a HWC display setup static void injectHwcDisplay(DisplayTransactionTest* test) { - FakeHwcDisplayInjector(DisplayVariant::TYPE, HWC_DISPLAY_TYPE) + const auto displayId = DisplayVariant::DISPLAY_ID::get(); + ASSERT_TRUE(displayId); + FakeHwcDisplayInjector(*displayId, HWC_DISPLAY_TYPE, + static_cast(DisplayVariant::PRIMARY)) .setHwcDisplayId(HWC_DISPLAY_ID) .setWidth(DisplayVariant::WIDTH) .setHeight(DisplayVariant::HEIGHT) @@ -362,8 +425,16 @@ struct HwcDisplayVariant { getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID, IComposerClient::Attribute::DPI_Y, _)) .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE))); - EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _)) - .WillRepeatedly(Return(Error::UNSUPPORTED)); + + if (PhysicalDisplay::HAS_IDENTIFICATION_DATA) { + EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _)) + .WillOnce(DoAll(SetArgPointee<1>(PhysicalDisplay::PORT), + SetArgPointee<2>(PhysicalDisplay::GET_IDENTIFICATION_DATA()), + Return(Error::NONE))); + } else { + EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _)) + .WillOnce(Return(Error::UNSUPPORTED)); + } } // Called by tests to set up HWC call expectations @@ -373,50 +444,67 @@ struct HwcDisplayVariant { } }; -struct NonHwcDisplayVariant { - static void injectHwcDisplay(DisplayTransactionTest*) {} - - static void setupHwcGetActiveConfigCallExpectations(DisplayTransactionTest* test) { - EXPECT_CALL(*test->mComposer, getActiveConfig(_, _)).Times(0); - } -}; - // Physical displays are expected to be synchronous, secure, and have a HWC display for output. constexpr uint32_t GRALLOC_USAGE_PHYSICAL_DISPLAY = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_FB; -template struct PhysicalDisplayVariant - : public DisplayVariant, - public HwcDisplayVariant> {}; + : DisplayVariant, width, height, critical, Async::FALSE, + Secure::TRUE, PhysicalDisplay::PRIMARY, GRALLOC_USAGE_PHYSICAL_DISPLAY>, + HwcDisplayVariant, width, height, + critical, Async::FALSE, Secure::TRUE, + PhysicalDisplay::PRIMARY, GRALLOC_USAGE_PHYSICAL_DISPLAY>, + PhysicalDisplay> {}; + +template +struct PrimaryDisplay { + static constexpr Primary PRIMARY = Primary::TRUE; + static constexpr uint8_t PORT = 255; + static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData; + static constexpr auto GET_IDENTIFICATION_DATA = getInternalEdid; +}; + +template +struct ExternalDisplay { + static constexpr Primary PRIMARY = Primary::FALSE; + static constexpr uint8_t PORT = 254; + static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData; + static constexpr auto GET_IDENTIFICATION_DATA = getExternalEdid; +}; + +struct TertiaryDisplay { + static constexpr Primary PRIMARY = Primary::FALSE; +}; // A primary display is a physical display that is critical using PrimaryDisplayVariant = - PhysicalDisplayVariant<1001, DisplayDevice::DISPLAY_PRIMARY, 3840, 2160, Critical::TRUE>; + PhysicalDisplayVariant<1001, PrimaryDisplay, 3840, 2160, Critical::TRUE>; // An external display is physical display that is not critical. using ExternalDisplayVariant = - PhysicalDisplayVariant<1002, DisplayDevice::DISPLAY_EXTERNAL, 1920, 1280, Critical::FALSE>; + PhysicalDisplayVariant<1002, ExternalDisplay, 1920, 1280, Critical::FALSE>; using TertiaryDisplayVariant = - PhysicalDisplayVariant<1003, DisplayDevice::DISPLAY_EXTERNAL, 1600, 1200, Critical::FALSE>; + PhysicalDisplayVariant<1003, TertiaryDisplay, 1600, 1200, Critical::FALSE>; // A virtual display not supported by the HWC. constexpr uint32_t GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY = 0; template struct NonHwcVirtualDisplayVariant - : public DisplayVariant, - public NonHwcDisplayVariant { - using Base = DisplayVariant; + : DisplayVariant { + using Base = DisplayVariant; + + static void injectHwcDisplay(DisplayTransactionTest*) {} + + static void setupHwcGetActiveConfigCallExpectations(DisplayTransactionTest* test) { + EXPECT_CALL(*test->mComposer, getActiveConfig(_, _)).Times(0); + } static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) { Base::setupNativeWindowSurfaceCreationCallExpectations(test); @@ -429,14 +517,14 @@ constexpr uint32_t GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY = GRALLOC_USAGE_HW_COMPOSER template struct HwcVirtualDisplayVariant - : public DisplayVariant, - public HwcDisplayVariant<1010, HWC2::DisplayType::Virtual, - NonHwcVirtualDisplayVariant> { - using Base = - DisplayVariant; + : DisplayVariant, width, height, Critical::FALSE, Async::TRUE, secure, + Primary::FALSE, GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY>, + HwcDisplayVariant< + 1010, HWC2::DisplayType::Virtual, + DisplayVariant, width, height, Critical::FALSE, Async::TRUE, + secure, Primary::FALSE, GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY>> { + using Base = DisplayVariant, width, height, Critical::FALSE, Async::TRUE, + secure, Primary::FALSE, GRALLOC_USAGE_HW_COMPOSER>; using Self = HwcVirtualDisplayVariant; static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) { @@ -850,8 +938,8 @@ TEST_F(DisplayTransactionTest, createDisplaySetsCurrentStateForNonsecureDisplay) // The display should have been added to the current state ASSERT_TRUE(hasCurrentDisplayState(displayToken)); const auto& display = getCurrentDisplayState(displayToken); - EXPECT_EQ(DisplayDevice::DISPLAY_VIRTUAL, display.type); - EXPECT_EQ(false, display.isSecure); + EXPECT_TRUE(display.isVirtual()); + EXPECT_FALSE(display.isSecure); EXPECT_EQ(name.string(), display.displayName); // -------------------------------------------------------------------- @@ -881,8 +969,8 @@ TEST_F(DisplayTransactionTest, createDisplaySetsCurrentStateForSecureDisplay) { // The display should have been added to the current state ASSERT_TRUE(hasCurrentDisplayState(displayToken)); const auto& display = getCurrentDisplayState(displayToken); - EXPECT_EQ(DisplayDevice::DISPLAY_VIRTUAL, display.type); - EXPECT_EQ(true, display.isSecure); + EXPECT_TRUE(display.isVirtual()); + EXPECT_TRUE(display.isSecure); EXPECT_EQ(name.string(), display.displayName); // -------------------------------------------------------------------- @@ -1002,9 +1090,12 @@ TEST_F(DisplayTransactionTest, resetDisplayStateClearsState) { */ class GetBestColorModeTest : public DisplayTransactionTest { public: + static constexpr DisplayId DEFAULT_DISPLAY_ID = 777; + GetBestColorModeTest() : DisplayTransactionTest(), - mInjector(FakeDisplayDeviceInjector(mFlinger, DisplayDevice::DISPLAY_PRIMARY, 0)) {} + mInjector(FakeDisplayDeviceInjector(mFlinger, DEFAULT_DISPLAY_ID, false /* isVirtual */, + true /* isPrimary */)) {} void setHasWideColorGamut(bool hasWideColorGamut) { mHasWideColorGamut = hasWideColorGamut; } @@ -1127,18 +1218,22 @@ void SetupNewDisplayDeviceInternalTest::setupNewDisplayDeviceInternalTest() { // Invocation DisplayDeviceState state; - state.type = Case::Display::TYPE; + state.displayId = static_cast(Case::Display::VIRTUAL) ? std::nullopt + : Case::Display::DISPLAY_ID::get(); state.isSecure = static_cast(Case::Display::SECURE); - auto device = mFlinger.setupNewDisplayDeviceInternal(displayToken, Case::Display::TYPE, state, - displaySurface, producer); + auto device = + mFlinger.setupNewDisplayDeviceInternal(displayToken, Case::Display::DISPLAY_ID::get(), + state, displaySurface, producer); // -------------------------------------------------------------------- // Postconditions ASSERT_TRUE(device != nullptr); - EXPECT_EQ(Case::Display::TYPE, device->getDisplayType()); + EXPECT_EQ(Case::Display::DISPLAY_ID::get(), device->getId()); + EXPECT_EQ(static_cast(Case::Display::VIRTUAL), device->isVirtual()); EXPECT_EQ(static_cast(Case::Display::SECURE), device->isSecure()); + EXPECT_EQ(static_cast(Case::Display::PRIMARY), device->isPrimary()); EXPECT_EQ(Case::Display::WIDTH, device->getWidth()); EXPECT_EQ(Case::Display::HEIGHT, device->getHeight()); EXPECT_EQ(Case::WideColorSupport::WIDE_COLOR_SUPPORTED, device->hasWideColorGamut()); @@ -1166,11 +1261,14 @@ TEST_F(SetupNewDisplayDeviceInternalTest, createNonHwcVirtualDisplay) { } TEST_F(SetupNewDisplayDeviceInternalTest, createHwcVirtualDisplay) { - // We need to resize this so that the HWC thinks the virtual display - // is something it created. - mFlinger.mutableHwcDisplayData().resize(3); + using Case = HwcVirtualDisplayCase; - setupNewDisplayDeviceInternalTest(); + // Insert display data so that the HWC thinks it created the virtual display. + const auto displayId = Case::Display::DISPLAY_ID::get(); + ASSERT_TRUE(displayId); + mFlinger.mutableHwcDisplayData()[*displayId] = {}; + + setupNewDisplayDeviceInternalTest(); } TEST_F(SetupNewDisplayDeviceInternalTest, createWideColorP3Display) { @@ -1258,7 +1356,7 @@ void HandleTransactionLockedTest::setupCommonCallExpectationsForConnectProcessin EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1); EXPECT_CALL(*mEventThread, - onHotplugReceived(Case::Display::TYPE == DisplayDevice::DISPLAY_PRIMARY + onHotplugReceived(static_cast(Case::Display::PRIMARY) ? EventThread::DisplayType::Primary : EventThread::DisplayType::External, true)) @@ -1269,7 +1367,7 @@ template void HandleTransactionLockedTest::setupCommonCallExpectationsForDisconnectProcessing() { EXPECT_CALL(*mSurfaceInterceptor, saveDisplayDeletion(_)).Times(1); EXPECT_CALL(*mEventThread, - onHotplugReceived(Case::Display::TYPE == DisplayDevice::DISPLAY_PRIMARY + onHotplugReceived(static_cast(Case::Display::PRIMARY) ? EventThread::DisplayType::Primary : EventThread::DisplayType::External, false)) @@ -1282,30 +1380,35 @@ void HandleTransactionLockedTest::verifyDisplayIsConnected(const sp& di ASSERT_TRUE(hasDisplayDevice(displayToken)); const auto& device = getDisplayDevice(displayToken); EXPECT_EQ(static_cast(Case::Display::SECURE), device->isSecure()); - EXPECT_EQ(Case::Display::TYPE == DisplayDevice::DISPLAY_PRIMARY, device->isPrimary()); + EXPECT_EQ(static_cast(Case::Display::PRIMARY), device->isPrimary()); // The display should have been set up in the current display state ASSERT_TRUE(hasCurrentDisplayState(displayToken)); const auto& current = getCurrentDisplayState(displayToken); - EXPECT_EQ(Case::Display::TYPE, current.type); + EXPECT_EQ(static_cast(Case::Display::VIRTUAL), current.isVirtual()); + EXPECT_EQ(static_cast(Case::Display::VIRTUAL) ? std::nullopt + : Case::Display::DISPLAY_ID::get(), + current.displayId); // The display should have been set up in the drawing display state ASSERT_TRUE(hasDrawingDisplayState(displayToken)); const auto& draw = getDrawingDisplayState(displayToken); - EXPECT_EQ(Case::Display::TYPE, draw.type); + EXPECT_EQ(static_cast(Case::Display::VIRTUAL), draw.isVirtual()); + EXPECT_EQ(static_cast(Case::Display::VIRTUAL) ? std::nullopt + : Case::Display::DISPLAY_ID::get(), + draw.displayId); } template void HandleTransactionLockedTest::verifyPhysicalDisplayIsConnected() { // HWComposer should have an entry for the display - EXPECT_TRUE(hasHwcDisplay(Case::Display::HWC_DISPLAY_ID)); + EXPECT_TRUE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID)); - // The display should be set up as a built-in display. - static_assert(0 <= Case::Display::TYPE && - Case::Display::TYPE < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES, - "Must use a valid physical display type index for the fixed-size array"); - auto& displayToken = mFlinger.mutableDisplayTokens()[Case::Display::TYPE]; - ASSERT_TRUE(displayToken != nullptr); + // SF should have a display token. + const auto displayId = Case::Display::DISPLAY_ID::get(); + ASSERT_TRUE(displayId); + ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(*displayId) == 1); + auto& displayToken = mFlinger.mutablePhysicalDisplayTokens()[*displayId]; verifyDisplayIsConnected(displayToken); } @@ -1371,7 +1474,7 @@ void HandleTransactionLockedTest::ignoresHotplugConnectCommon() { // Postconditions // HWComposer should not have an entry for the display - EXPECT_FALSE(hasHwcDisplay(Case::Display::HWC_DISPLAY_ID)); + EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID)); } template @@ -1407,13 +1510,12 @@ void HandleTransactionLockedTest::processesHotplugDisconnectCommon() { // Postconditions // HWComposer should not have an entry for the display - EXPECT_FALSE(hasHwcDisplay(Case::Display::HWC_DISPLAY_ID)); + EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID)); - // The display should not be set up as a built-in display. - ASSERT_TRUE(0 <= Case::Display::TYPE && - Case::Display::TYPE < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES); - auto displayToken = mFlinger.mutableDisplayTokens()[Case::Display::TYPE]; - EXPECT_TRUE(displayToken == nullptr); + // SF should not have a display token. + const auto displayId = Case::Display::DISPLAY_ID::get(); + ASSERT_TRUE(displayId); + ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(*displayId) == 0); // The existing token should have been removed verifyDisplayIsNotConnected(existing.token()); @@ -1500,13 +1602,12 @@ TEST_F(HandleTransactionLockedTest, processesHotplugConnectThenDisconnectPrimary // Postconditions // HWComposer should not have an entry for the display - EXPECT_FALSE(hasHwcDisplay(Case::Display::HWC_DISPLAY_ID)); + EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID)); - // The display should not be set up as a primary built-in display. - ASSERT_TRUE(0 <= Case::Display::TYPE && - Case::Display::TYPE < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES); - auto displayToken = mFlinger.mutableDisplayTokens()[Case::Display::TYPE]; - EXPECT_TRUE(displayToken == nullptr); + // SF should not have a display token. + const auto displayId = Case::Display::DISPLAY_ID::get(); + ASSERT_TRUE(displayId); + ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(*displayId) == 0); } TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectThenConnectPrimary) { @@ -1545,10 +1646,10 @@ TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectThenConnectPrimary // The existing token should have been removed verifyDisplayIsNotConnected(existing.token()); - static_assert(0 <= Case::Display::TYPE && - Case::Display::TYPE < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES, - "Display type must be a built-in display"); - EXPECT_NE(existing.token(), mFlinger.mutableDisplayTokens()[Case::Display::TYPE]); + const auto displayId = Case::Display::DISPLAY_ID::get(); + ASSERT_TRUE(displayId); + ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(*displayId) == 1); + EXPECT_NE(existing.token(), mFlinger.mutablePhysicalDisplayTokens()[*displayId]); // A new display should be connected in its place @@ -1578,13 +1679,12 @@ TEST_F(HandleTransactionLockedTest, processesVirtualDisplayAdded) { // surface(producer) sp displayToken = new BBinder(); - DisplayDeviceState info; - info.type = Case::Display::TYPE; - info.isSecure = static_cast(Case::Display::SECURE); + DisplayDeviceState state; + state.isSecure = static_cast(Case::Display::SECURE); sp surface{new mock::GraphicBufferProducer()}; - info.surface = surface; - mFlinger.mutableCurrentState().displays.add(displayToken, info); + state.surface = surface; + mFlinger.mutableCurrentState().displays.add(displayToken, state); // -------------------------------------------------------------------- // Call Expectations @@ -1646,11 +1746,10 @@ TEST_F(HandleTransactionLockedTest, processesVirtualDisplayAddedWithNoSurface) { // surface. sp displayToken = new BBinder(); - DisplayDeviceState info; - info.type = Case::Display::TYPE; - info.isSecure = static_cast(Case::Display::SECURE); + DisplayDeviceState state; + state.isSecure = static_cast(Case::Display::SECURE); - mFlinger.mutableCurrentState().displays.add(displayToken, info); + mFlinger.mutableCurrentState().displays.add(displayToken, state); // -------------------------------------------------------------------- // Call Expectations @@ -1669,7 +1768,7 @@ TEST_F(HandleTransactionLockedTest, processesVirtualDisplayAddedWithNoSurface) { // The drawing display state will be set from the current display state. ASSERT_TRUE(hasDrawingDisplayState(displayToken)); const auto& draw = getDrawingDisplayState(displayToken); - EXPECT_EQ(Case::Display::TYPE, draw.type); + EXPECT_EQ(static_cast(Case::Display::VIRTUAL), draw.isVirtual()); } TEST_F(HandleTransactionLockedTest, processesVirtualDisplayRemoval) { @@ -1679,7 +1778,9 @@ TEST_F(HandleTransactionLockedTest, processesVirtualDisplayRemoval) { // Preconditions // A virtual display is set up but is removed from the current state. - mFlinger.mutableHwcDisplayData().resize(3); + const auto displayId = Case::Display::DISPLAY_ID::get(); + ASSERT_TRUE(displayId); + mFlinger.mutableHwcDisplayData()[*displayId] = {}; Case::Display::injectHwcDisplay(this); auto existing = Case::Display::makeFakeExistingDisplayInjector(this); existing.inject(); @@ -2799,9 +2900,10 @@ TEST_F(SetPowerModeInternalTest, setPowerModeInternalDoesNothingIfVirtualDisplay // -------------------------------------------------------------------- // Preconditions - // We need to resize this so that the HWC thinks the virtual display - // is something it created. - mFlinger.mutableHwcDisplayData().resize(3); + // Insert display data so that the HWC thinks it created the virtual display. + const auto displayId = Case::Display::DISPLAY_ID::get(); + ASSERT_TRUE(displayId); + mFlinger.mutableHwcDisplayData()[*displayId] = {}; // A virtual display device is set up Case::Display::injectHwcDisplay(this); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index c3534e83a8..b046e4a83c 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -178,10 +178,6 @@ public: layer->getBE().compositionInfo.hwc.sidebandStream = sidebandStream; } - void setLayerCompositionType(sp layer, HWC2::Composition type) { - layer->getBE().mHwcLayers[DisplayDevice::DISPLAY_PRIMARY].compositionType = type; - }; - void setLayerPotentialCursor(sp layer, bool potentialCursor) { layer->mPotentialCursor = potentialCursor; } @@ -200,7 +196,8 @@ public: auto resetDisplayState() { return mFlinger->resetDisplayState(); } - auto setupNewDisplayDeviceInternal(const wp& displayToken, int32_t displayId, + auto setupNewDisplayDeviceInternal(const wp& displayToken, + const std::optional& displayId, const DisplayDeviceState& state, const sp& dispSurface, const sp& producer) { @@ -263,7 +260,6 @@ public: auto& mutableCurrentState() { return mFlinger->mCurrentState; } auto& mutableDisplayColorSetting() { return mFlinger->mDisplayColorSetting; } auto& mutableDisplays() { return mFlinger->mDisplays; } - auto& mutableDisplayTokens() { return mFlinger->mDisplayTokens; } auto& mutableDrawingState() { return mFlinger->mDrawingState; } auto& mutableEventControlThread() { return mFlinger->mEventControlThread; } auto& mutableEventQueue() { return mFlinger->mEventQueue; } @@ -273,6 +269,7 @@ public: auto& mutableInterceptor() { return mFlinger->mInterceptor; } auto& mutableMainThreadId() { return mFlinger->mMainThreadId; } auto& mutablePendingHotplugEvents() { return mFlinger->mPendingHotplugEvents; } + auto& mutablePhysicalDisplayTokens() { return mFlinger->mPhysicalDisplayTokens; } auto& mutablePrimaryDispSync() { return mFlinger->mPrimaryDispSync; } auto& mutablePrimaryHWVsyncEnabled() { return mFlinger->mPrimaryHWVsyncEnabled; } auto& mutableTexturePool() { return mFlinger->mTexturePool; } @@ -280,8 +277,13 @@ public: auto& mutableUseHwcVirtualDisplays() { return mFlinger->mUseHwcVirtualDisplays; } auto& mutableComposerSequenceId() { return mFlinger->getBE().mComposerSequenceId; } - auto& mutableHwcDisplayData() { return mFlinger->getBE().mHwc->mDisplayData; } - auto& mutableHwcDisplaySlots() { return mFlinger->getBE().mHwc->mHwcDisplaySlots; } + auto& mutableHwcDisplayData() { return mFlinger->getHwComposer().mDisplayData; } + auto& mutableHwcPhysicalDisplayIdMap() { + return mFlinger->getHwComposer().mPhysicalDisplayIdMap; + } + + auto& mutableInternalHwcDisplayId() { return mFlinger->getHwComposer().mInternalHwcDisplayId; } + auto& mutableExternalHwcDisplayId() { return mFlinger->getHwComposer().mExternalHwcDisplayId; } ~TestableSurfaceFlinger() { // All these pointer and container clears help ensure that GMock does @@ -333,8 +335,9 @@ public: static constexpr int32_t DEFAULT_DPI = 320; static constexpr int32_t DEFAULT_ACTIVE_CONFIG = 0; - FakeHwcDisplayInjector(DisplayDevice::DisplayType type, HWC2::DisplayType hwcDisplayType) - : mType(type), mHwcDisplayType(hwcDisplayType) {} + FakeHwcDisplayInjector(DisplayId displayId, HWC2::DisplayType hwcDisplayType, + bool isPrimary) + : mDisplayId(displayId), mHwcDisplayType(hwcDisplayType), mIsPrimary(isPrimary) {} auto& setHwcDisplayId(hwc2_display_t displayId) { mHwcDisplayId = displayId; @@ -403,17 +406,22 @@ public: display->mutableConfigs().emplace(mActiveConfig, config.build()); display->mutableIsConnected() = true; - ASSERT_TRUE(flinger->mutableHwcDisplayData().size() > static_cast(mType)); - flinger->mutableHwcDisplayData()[mType] = HWComposer::DisplayData(); - flinger->mutableHwcDisplayData()[mType].hwcDisplay = display.get(); - flinger->mutableHwcDisplaySlots().emplace(mHwcDisplayId, mType); + flinger->mutableHwcDisplayData()[mDisplayId].hwcDisplay = display.get(); + + if (mHwcDisplayType == HWC2::DisplayType::Physical) { + flinger->mutableHwcPhysicalDisplayIdMap().emplace(mHwcDisplayId, mDisplayId); + (mIsPrimary ? flinger->mutableInternalHwcDisplayId() + : flinger->mutableExternalHwcDisplayId()) = mHwcDisplayId; + } flinger->mFakeHwcDisplays.push_back(std::move(display)); } private: - DisplayDevice::DisplayType mType; - HWC2::DisplayType mHwcDisplayType; + const DisplayId mDisplayId; + const HWC2::DisplayType mHwcDisplayType; + const bool mIsPrimary; + hwc2_display_t mHwcDisplayId = DEFAULT_HWC_DISPLAY_ID; int32_t mWidth = DEFAULT_WIDTH; int32_t mHeight = DEFAULT_HEIGHT; @@ -427,10 +435,13 @@ public: class FakeDisplayDeviceInjector { public: - FakeDisplayDeviceInjector(TestableSurfaceFlinger& flinger, DisplayDevice::DisplayType type, - int32_t displayId) - : mFlinger(flinger), - mCreationArgs(flinger.mFlinger.get(), mDisplayToken, type, displayId) {} + FakeDisplayDeviceInjector(TestableSurfaceFlinger& flinger, + const std::optional& displayId, bool isVirtual, + bool isPrimary) + : mFlinger(flinger), mCreationArgs(flinger.mFlinger.get(), mDisplayToken, displayId) { + mCreationArgs.isVirtual = isVirtual; + mCreationArgs.isPrimary = isPrimary; + } sp token() const { return mDisplayToken; } @@ -497,7 +508,7 @@ public: sp inject() { DisplayDeviceState state; - state.type = mCreationArgs.type; + state.displayId = mCreationArgs.isVirtual ? std::nullopt : mCreationArgs.displayId; state.isSecure = mCreationArgs.isSecure; sp device = new DisplayDevice(std::move(mCreationArgs)); @@ -505,9 +516,9 @@ public: mFlinger.mutableCurrentState().displays.add(mDisplayToken, state); mFlinger.mutableDrawingState().displays.add(mDisplayToken, state); - if (state.type >= DisplayDevice::DISPLAY_PRIMARY && - state.type < DisplayDevice::DISPLAY_VIRTUAL) { - mFlinger.mutableDisplayTokens()[state.type] = mDisplayToken; + if (!mCreationArgs.isVirtual) { + LOG_ALWAYS_FATAL_IF(!state.displayId); + mFlinger.mutablePhysicalDisplayTokens()[*state.displayId] = mDisplayToken; } return device; -- cgit v1.2.3-59-g8ed1b From e2ffb426c3c48bbc93bc2cfc28b33b6f6e0ddfa2 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Fri, 12 Oct 2018 11:33:52 -0700 Subject: blast: Send transaction callback Send transaction callback to client via the TransactionCompletedListener. Test: Transaction_test Bug: 80477568 Change-Id: Iac98780b1357b9cc54b93cc3c848013b28fab441 --- libs/gui/ITransactionCompletedListener.cpp | 75 ++++++++- libs/gui/SurfaceComposerClient.cpp | 29 +++- .../include/gui/ITransactionCompletedListener.h | 56 ++++++- libs/gui/include/gui/SurfaceComposerClient.h | 15 +- services/surfaceflinger/Android.bp | 1 + services/surfaceflinger/BufferStateLayer.cpp | 37 +++++ services/surfaceflinger/BufferStateLayer.h | 2 + services/surfaceflinger/Layer.cpp | 1 + services/surfaceflinger/Layer.h | 9 ++ services/surfaceflinger/SurfaceFlinger.cpp | 21 ++- services/surfaceflinger/SurfaceFlinger.h | 7 + .../surfaceflinger/TransactionCompletedThread.cpp | 168 +++++++++++++++++++++ .../surfaceflinger/TransactionCompletedThread.h | 102 +++++++++++++ 13 files changed, 503 insertions(+), 20 deletions(-) create mode 100644 services/surfaceflinger/TransactionCompletedThread.cpp create mode 100644 services/surfaceflinger/TransactionCompletedThread.h (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp index 38ff59d746..3ecd13c28c 100644 --- a/libs/gui/ITransactionCompletedListener.cpp +++ b/libs/gui/ITransactionCompletedListener.cpp @@ -30,6 +30,74 @@ enum class Tag : uint32_t { } // Anonymous namespace +status_t SurfaceStats::writeToParcel(Parcel* output) const { + return output->writeStrongBinder(surfaceControl); +} + +status_t SurfaceStats::readFromParcel(const Parcel* input) { + return input->readStrongBinder(&surfaceControl); +} + +status_t TransactionStats::writeToParcel(Parcel* output) const { + return output->writeParcelableVector(surfaceStats); +} + +status_t TransactionStats::readFromParcel(const Parcel* input) { + return input->readParcelableVector(&surfaceStats); +} + +status_t ListenerStats::writeToParcel(Parcel* output) const { + status_t err = output->writeInt32(static_cast(transactionStats.size())); + if (err != NO_ERROR) { + return err; + } + + for (const auto& [callbackIds, stats] : transactionStats) { + err = output->writeParcelable(stats); + if (err != NO_ERROR) { + return err; + } + err = output->writeInt64Vector(callbackIds); + if (err != NO_ERROR) { + return err; + } + } + return NO_ERROR; +} + +status_t ListenerStats::readFromParcel(const Parcel* input) { + int32_t transactionStats_size = input->readInt32(); + + for (int i = 0; i < transactionStats_size; i++) { + TransactionStats stats; + std::vector callbackIds; + + status_t err = input->readParcelable(&stats); + if (err != NO_ERROR) { + return err; + } + err = input->readInt64Vector(&callbackIds); + if (err != NO_ERROR) { + return err; + } + + transactionStats.emplace(callbackIds, stats); + } + return NO_ERROR; +} + +ListenerStats ListenerStats::createEmpty(const sp& listener, + const std::unordered_set& callbackIds) { + ListenerStats listenerStats; + listenerStats.listener = listener; + TransactionStats transactionStats; + listenerStats.transactionStats.emplace(std::piecewise_construct, + std::forward_as_tuple(callbackIds.begin(), + callbackIds.end()), + std::forward_as_tuple(transactionStats)); + return listenerStats; +} + class BpTransactionCompletedListener : public SafeBpInterface { public: explicit BpTransactionCompletedListener(const sp& impl) @@ -38,9 +106,10 @@ public: ~BpTransactionCompletedListener() override; - void onTransactionCompleted() override { - callRemoteAsync( - Tag::ON_TRANSACTION_COMPLETED); + void onTransactionCompleted(ListenerStats stats) override { + callRemoteAsync(Tag::ON_TRANSACTION_COMPLETED, + stats); } }; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 88c574286b..e10bda485b 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -128,8 +128,7 @@ void TransactionCompletedListener::startListeningLocked() { mListening = true; } -CallbackId TransactionCompletedListener::addCallback( - const TransactionCompletedCallbackWithContext& callback) { +CallbackId TransactionCompletedListener::addCallback(const TransactionCompletedCallback& callback) { std::lock_guard lock(mMutex); startListeningLocked(); @@ -138,8 +137,20 @@ CallbackId TransactionCompletedListener::addCallback( return callbackId; } -void TransactionCompletedListener::onTransactionCompleted() { - return; +void TransactionCompletedListener::onTransactionCompleted(ListenerStats listenerStats) { + std::lock_guard lock(mMutex); + + for (const auto& [callbackIds, transactionStats] : listenerStats.transactionStats) { + for (auto callbackId : callbackIds) { + const auto& callback = mCallbacks[callbackId]; + if (!callback) { + ALOGE("cannot call null callback function, skipping"); + continue; + } + callback(transactionStats); + mCallbacks.erase(callbackId); + } + } } // --------------------------------------------------------------------------- @@ -201,6 +212,12 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { continue; } + // If the listener does not have any SurfaceControls set on this Transaction, send the + // callback now + if (surfaceControls.empty()) { + listener->onTransactionCompleted(ListenerStats::createEmpty(listener, callbackIds)); + } + // If the listener has any SurfaceControls set on this Transaction update the surface state for (const auto& surfaceControl : surfaceControls) { layer_state_t* s = getLayerState(surfaceControl); @@ -676,10 +693,10 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSideb SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::addTransactionCompletedCallback( - TransactionCompletedCallback callback, void* callbackContext) { + TransactionCompletedCallbackTakesContext callback, void* callbackContext) { auto listener = TransactionCompletedListener::getInstance(); - auto callbackWithContext = std::bind(callback, callbackContext); + auto callbackWithContext = std::bind(callback, callbackContext, std::placeholders::_1); CallbackId callbackId = listener->addCallback(callbackWithContext); diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h index 0a61cd1c9b..3c4c393172 100644 --- a/libs/gui/include/gui/ITransactionCompletedListener.h +++ b/libs/gui/include/gui/ITransactionCompletedListener.h @@ -17,18 +17,70 @@ #pragma once #include +#include +#include #include +#include + #include +#include #include namespace android { +class ITransactionCompletedListener; + +using CallbackId = int64_t; + +struct CallbackIdsHash { + // CallbackId vectors have several properties that let us get away with this simple hash. + // 1) CallbackIds are never 0 so if something has gone wrong and our CallbackId vector is + // empty we can still hash 0. + // 2) CallbackId vectors for the same listener either are identical or contain none of the + // same members. It is sufficient to just check the first CallbackId in the vectors. If + // they match, they are the same. If they do not match, they are not the same. + std::size_t operator()(const std::vector callbackIds) const { + return std::hash{}((callbackIds.size() == 0) ? 0 : callbackIds.front()); + } +}; + +class SurfaceStats : public Parcelable { +public: + status_t writeToParcel(Parcel* output) const override; + status_t readFromParcel(const Parcel* input) override; + + SurfaceStats() = default; + explicit SurfaceStats(const sp& sc) : surfaceControl(sc) {} + + sp surfaceControl; +}; + +class TransactionStats : public Parcelable { +public: + status_t writeToParcel(Parcel* output) const override; + status_t readFromParcel(const Parcel* input) override; + + std::vector surfaceStats; +}; + +class ListenerStats : public Parcelable { +public: + status_t writeToParcel(Parcel* output) const override; + status_t readFromParcel(const Parcel* input) override; + + static ListenerStats createEmpty(const sp& listener, + const std::unordered_set& callbackIds); + + sp listener; + std::unordered_map, TransactionStats, CallbackIdsHash> transactionStats; +}; + class ITransactionCompletedListener : public IInterface { public: DECLARE_META_INTERFACE(TransactionCompletedListener) - virtual void onTransactionCompleted() = 0; + virtual void onTransactionCompleted(ListenerStats stats) = 0; }; class BnTransactionCompletedListener : public SafeBnInterface { @@ -40,8 +92,6 @@ public: uint32_t flags = 0) override; }; -using CallbackId = int64_t; - class ListenerCallbacks { public: ListenerCallbacks(const sp& listener, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 2ed4f8f3e4..1cafb77af1 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -52,8 +52,9 @@ class Region; // --------------------------------------------------------------------------- -using TransactionCompletedCallback = std::function; -using TransactionCompletedCallbackWithContext = std::function; +using TransactionCompletedCallbackTakesContext = + std::function; +using TransactionCompletedCallback = std::function; class TransactionCompletedListener : public BnTransactionCompletedListener { TransactionCompletedListener(); @@ -66,7 +67,7 @@ class TransactionCompletedListener : public BnTransactionCompletedListener { CallbackId mCallbackIdCounter GUARDED_BY(mMutex) = 1; - std::map mCallbacks GUARDED_BY(mMutex); + std::map mCallbacks GUARDED_BY(mMutex); public: static sp getInstance(); @@ -74,10 +75,10 @@ public: void startListeningLocked() REQUIRES(mMutex); - CallbackId addCallback(const TransactionCompletedCallbackWithContext& callback); + CallbackId addCallback(const TransactionCompletedCallback& callback); // Overrides BnTransactionCompletedListener's onTransactionCompleted - void onTransactionCompleted() override; + void onTransactionCompleted(ListenerStats stats) override; }; // --------------------------------------------------------------------------- @@ -303,8 +304,8 @@ public: Transaction& setSidebandStream(const sp& sc, const sp& sidebandStream); - Transaction& addTransactionCompletedCallback(TransactionCompletedCallback callback, - void* callbackContext); + Transaction& addTransactionCompletedCallback( + TransactionCompletedCallbackTakesContext callback, void* callbackContext); // Detaches all child surfaces (and their children recursively) // from their SurfaceControl. diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 16003a258c..0e75d7fe4c 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -153,6 +153,7 @@ filegroup { "SurfaceInterceptor.cpp", "SurfaceTracing.cpp", "TimeStats/TimeStats.cpp", + "TransactionCompletedThread.cpp", ], } diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 0e14d8c9d8..adc91a73e0 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -64,6 +64,12 @@ bool BufferStateLayer::shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { return hasFrameUpdate(); } +bool BufferStateLayer::willPresentCurrentTransaction() const { + // Returns true if the most recent Transaction applied to CurrentState will be presented. + return getSidebandStreamChanged() || getAutoRefresh() || + (mCurrentState.modified && mCurrentState.buffer != nullptr); +} + bool BufferStateLayer::getTransformToDisplayInverse() const { return mCurrentState.transformToDisplayInverse; } @@ -183,6 +189,34 @@ bool BufferStateLayer::setSidebandStream(const sp& sidebandStream) return true; } +bool BufferStateLayer::setTransactionCompletedListeners( + const std::vector>& handles) { + // If there is no handle, we will not send a callback + if (handles.empty()) { + return false; + } + + const bool willPresent = willPresentCurrentTransaction(); + + for (const auto& handle : handles) { + // If this layer will be presented in this frame + if (willPresent) { + // Notify the transaction completed thread that there is a pending latched callback + // handle + mFlinger->getTransactionCompletedThread().registerPendingLatchedCallbackHandle(handle); + + // Store so latched time and release fence can be set + mCurrentState.callbackHandles.push_back(handle); + + } else { // If this layer will NOT need to be relatched and presented this frame + // Notify the transaction completed thread this handle is done + mFlinger->getTransactionCompletedThread().addUnlatchedCallbackHandle(handle); + } + } + + return willPresent; +} + bool BufferStateLayer::setSize(uint32_t w, uint32_t h) { if (mCurrentState.active.w == w && mCurrentState.active.h == h) return false; mCurrentState.active.w = w; @@ -404,6 +438,9 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse return BAD_VALUE; } + mFlinger->getTransactionCompletedThread().addLatchedCallbackHandles( + getDrawingState().callbackHandles); + // Handle sync fences if (SyncFeatures::getInstance().useNativeFenceSync() && releaseFence != Fence::NO_FENCE) { // TODO(alecmouri): Fail somewhere upstream if the fence is invalid. diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index cf4d0f004b..fcea96dae6 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -69,6 +69,7 @@ public: bool setSurfaceDamageRegion(const Region& surfaceDamage) override; bool setApi(int32_t api) override; bool setSidebandStream(const sp& sidebandStream) override; + bool setTransactionCompletedListeners(const std::vector>& handles) override; bool setSize(uint32_t w, uint32_t h) override; bool setPosition(float x, float y, bool immediate) override; @@ -125,6 +126,7 @@ private: // ----------------------------------------------------------------------- private: void onFirstRef() override; + bool willPresentCurrentTransaction() const; static const std::array IDENTITY_MATRIX; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f29dfc0f1b..c1f0587b3c 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1049,6 +1049,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { // Commit the transaction commitTransaction(c); + mCurrentState.callbackHandles = {}; return flags; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 12671ff51d..9235b645a6 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -47,6 +47,7 @@ #include "MonitoredProducer.h" #include "SurfaceFlinger.h" #include "TimeStats/TimeStats.h" +#include "TransactionCompletedThread.h" #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/HWComposerBufferCache.h" @@ -183,6 +184,10 @@ public: sp sidebandStream; mat4 colorTransform; bool hasColorTransform; + + // The deque of callback handles for this frame. The back of the deque contains the most + // recent callback handle. + std::deque> callbackHandles; }; explicit Layer(const LayerCreationArgs& args); @@ -272,6 +277,10 @@ public: virtual bool setSurfaceDamageRegion(const Region& /*surfaceDamage*/) { return false; }; virtual bool setApi(int32_t /*api*/) { return false; }; virtual bool setSidebandStream(const sp& /*sidebandStream*/) { return false; }; + virtual bool setTransactionCompletedListeners( + const std::vector>& /*handles*/) { + return false; + }; ui::Dataspace getDataSpace() const { return mCurrentDataSpace; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index dec08fd629..643b1ce336 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1942,6 +1942,8 @@ void SurfaceFlinger::postComposition() ATRACE_INT("TexturePoolSize", mTexturePool.size()); } } + + mTransactionCompletedThread.sendCallbacks(); } void SurfaceFlinger::rebuildLayerStacks() { @@ -3295,9 +3297,15 @@ void SurfaceFlinger::setTransactionState( transactionFlags |= setDisplayStateLocked(display); } + uint32_t clientStateFlags = 0; for (const ComposerState& state : states) { - transactionFlags |= setClientStateLocked(state); + clientStateFlags |= setClientStateLocked(state); + } + // If the state doesn't require a traversal and there are callbacks, send them now + if (!(clientStateFlags & eTraversalNeeded)) { + mTransactionCompletedThread.sendCallbacks(); } + transactionFlags |= clientStateFlags; // Iterate through all layers again to determine if any need to be destroyed. Marking layers // as destroyed should only occur after setting all other states. This is to allow for a @@ -3606,6 +3614,17 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState if (what & layer_state_t::eSidebandStreamChanged) { if (layer->setSidebandStream(s.sidebandStream)) flags |= eTraversalNeeded; } + + std::vector> callbackHandles; + if ((what & layer_state_t::eListenerCallbacksChanged) && (!s.listenerCallbacks.empty())) { + mTransactionCompletedThread.run(); + for (const auto& [listener, callbackIds] : s.listenerCallbacks) { + callbackHandles.emplace_back(new CallbackHandle(listener, callbackIds, s.surface)); + } + } + if (layer->setTransactionCompletedListeners(callbackHandles)) flags |= eTraversalNeeded; + // Do not put anything that updates layer state or modifies flags after + // setTransactionCompletedListener return flags; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 51168a6724..18e1ca18b4 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -62,6 +62,7 @@ #include "SurfaceFlingerFactory.h" #include "SurfaceInterceptor.h" #include "SurfaceTracing.h" +#include "TransactionCompletedThread.h" #include "DisplayHardware/HWC2.h" #include "DisplayHardware/HWComposer.h" @@ -367,6 +368,10 @@ public: inline void onLayerCreated() { mNumLayers++; } inline void onLayerDestroyed() { mNumLayers--; } + TransactionCompletedThread& getTransactionCompletedThread() { + return mTransactionCompletedThread; + } + private: friend class Client; friend class DisplayEventConnection; @@ -886,6 +891,8 @@ private: bool mUseHwcVirtualDisplays = false; std::atomic mFrameMissedCount{0}; + TransactionCompletedThread mTransactionCompletedThread; + // Restrict layers to use two buffers in their bufferqueues. bool mLayerTripleBufferingDisabled = false; diff --git a/services/surfaceflinger/TransactionCompletedThread.cpp b/services/surfaceflinger/TransactionCompletedThread.cpp new file mode 100644 index 0000000000..e83422e23b --- /dev/null +++ b/services/surfaceflinger/TransactionCompletedThread.cpp @@ -0,0 +1,168 @@ +/* + * Copyright 2018 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 "TransactionCompletedThread" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "TransactionCompletedThread.h" + +#include + +#include +#include +#include + +namespace android { + +TransactionCompletedThread::~TransactionCompletedThread() { + { + std::lock_guard lock(mMutex); + mKeepRunning = false; + mConditionVariable.notify_all(); + } + + mThread.join(); + + { + std::lock_guard lock(mMutex); + for (const auto& [listener, listenerStats] : mListenerStats) { + listener->unlinkToDeath(mDeathRecipient); + } + } +} + +void TransactionCompletedThread::run() { + std::lock_guard lock(mMutex); + if (mRunning) { + return; + } + mDeathRecipient = new ThreadDeathRecipient(); + mRunning = true; + mThread = std::thread(&TransactionCompletedThread::threadMain, this); +} + +void TransactionCompletedThread::registerPendingLatchedCallbackHandle( + const sp& handle) { + std::lock_guard lock(mMutex); + + sp listener = IInterface::asBinder(handle->listener); + const auto& callbackIds = handle->callbackIds; + + mPendingTransactions[listener][callbackIds]++; +} + +void TransactionCompletedThread::addLatchedCallbackHandles( + const std::deque>& handles) { + std::lock_guard lock(mMutex); + + for (const auto& handle : handles) { + auto listener = mPendingTransactions.find(IInterface::asBinder(handle->listener)); + auto& pendingCallbacks = listener->second; + auto pendingCallback = pendingCallbacks.find(handle->callbackIds); + + if (pendingCallback != pendingCallbacks.end()) { + auto& pendingCount = pendingCallback->second; + + // Decrease the pending count for this listener + if (--pendingCount == 0) { + pendingCallbacks.erase(pendingCallback); + } + } else { + ALOGW("there are more latched callbacks than there were registered callbacks"); + } + + addCallbackHandle(handle); + } +} + +void TransactionCompletedThread::addUnlatchedCallbackHandle(const sp& handle) { + std::lock_guard lock(mMutex); + addCallbackHandle(handle); +} + +void TransactionCompletedThread::addCallbackHandle(const sp& handle) { + const sp listener = IInterface::asBinder(handle->listener); + + // If we don't already have a reference to this listener, linkToDeath so we get a notification + // if it dies. + if (mListenerStats.count(listener) == 0) { + status_t error = listener->linkToDeath(mDeathRecipient); + if (error != NO_ERROR) { + ALOGE("cannot add callback handle because linkToDeath failed, err: %d", error); + return; + } + } + + auto& listenerStats = mListenerStats[listener]; + listenerStats.listener = handle->listener; + + auto& transactionStats = listenerStats.transactionStats[handle->callbackIds]; + transactionStats.surfaceStats.emplace_back(handle->surfaceControl); +} + +void TransactionCompletedThread::sendCallbacks() { + std::lock_guard lock(mMutex); + if (mRunning) { + mConditionVariable.notify_all(); + } +} + +void TransactionCompletedThread::threadMain() { + std::lock_guard lock(mMutex); + + while (mKeepRunning) { + mConditionVariable.wait(mMutex); + + // For each listener + auto it = mListenerStats.begin(); + while (it != mListenerStats.end()) { + auto& [listener, listenerStats] = *it; + + // For each transaction + bool sendCallback = true; + for (auto& [callbackIds, transactionStats] : listenerStats.transactionStats) { + // If we are still waiting on the callback handles for this transaction, skip it + if (mPendingTransactions[listener].count(callbackIds) != 0) { + sendCallback = false; + break; + } + } + // If the listener has no pending transactions and all latched transactions have been + // presented + if (sendCallback) { + // If the listener is still alive + if (listener->isBinderAlive()) { + // Send callback + listenerStats.listener->onTransactionCompleted(listenerStats); + listener->unlinkToDeath(mDeathRecipient); + } + it = mListenerStats.erase(it); + } else { + it++; + } + } + } +} + +// ----------------------------------------------------------------------- + +CallbackHandle::CallbackHandle(const sp& transactionListener, + const std::vector& ids, const sp& sc) + : listener(transactionListener), callbackIds(ids), surfaceControl(sc) {} + +} // namespace android diff --git a/services/surfaceflinger/TransactionCompletedThread.h b/services/surfaceflinger/TransactionCompletedThread.h new file mode 100644 index 0000000000..39cf7e877c --- /dev/null +++ b/services/surfaceflinger/TransactionCompletedThread.h @@ -0,0 +1,102 @@ +/* + * Copyright 2018 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 +#include +#include +#include +#include + +#include + +#include +#include + +namespace android { + +class CallbackHandle : public RefBase { +public: + CallbackHandle(const sp& transactionListener, + const std::vector& ids, const sp& sc); + + sp listener; + std::vector callbackIds; + sp surfaceControl; +}; + +class TransactionCompletedThread { +public: + ~TransactionCompletedThread(); + + void run(); + + // Informs the TransactionCompletedThread that there is a Transaction with a CallbackHandle + // that needs to be latched and presented this frame. This function should be called once the + // layer has received the CallbackHandle so the TransactionCompletedThread knows not to send + // a callback for that Listener/Transaction pair until that CallbackHandle has been latched and + // presented. + void registerPendingLatchedCallbackHandle(const sp& handle); + // Notifies the TransactionCompletedThread that a pending CallbackHandle has been latched. + void addLatchedCallbackHandles(const std::deque>& handles); + + // Adds the Transaction CallbackHandle from a layer that does not need to be relatched and + // presented this frame. + void addUnlatchedCallbackHandle(const sp& handle); + + void sendCallbacks(); + +private: + void threadMain(); + + void addCallbackHandle(const sp& handle) REQUIRES(mMutex); + + class ThreadDeathRecipient : public IBinder::DeathRecipient { + public: + // This function is a no-op. isBinderAlive needs a linked DeathRecipient to work. + // Death recipients needs a binderDied function. + // + // (isBinderAlive checks if BpBinder's mAlive is 0. mAlive is only set to 0 in sendObituary. + // sendObituary is only called if linkToDeath was called with a DeathRecipient.) + void binderDied(const wp& /*who*/) override {} + }; + sp mDeathRecipient; + + struct IBinderHash { + std::size_t operator()(const sp& strongPointer) const { + return std::hash{}(strongPointer.get()); + } + }; + + std::thread mThread; + + std::mutex mMutex; + std::condition_variable_any mConditionVariable; + + std::unordered_map< + sp, + std::unordered_map, uint32_t /*count*/, CallbackIdsHash>, + IBinderHash> + mPendingTransactions GUARDED_BY(mMutex); + std::unordered_map, ListenerStats, IBinderHash> mListenerStats + GUARDED_BY(mMutex); + + bool mRunning GUARDED_BY(mMutex) = false; + bool mKeepRunning GUARDED_BY(mMutex) = true; +}; + +} // namespace android -- cgit v1.2.3-59-g8ed1b From f2deb82e2703ab66139babce9dee02259967019f Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Mon, 12 Nov 2018 17:53:48 -0800 Subject: SF: Disable transform hint when the layer uses getTransformToDisplayInverse flag In some cases such as camera viewfinder, the app always submits buffer in one orientation and aligns with the device orientation with by setting the getTransformToDisplayInverse flag. If the device rotates, SF will send a transform hint to gl consumer which will rotate the buffer. If the surface sets the getTransformToDisplayInverse flag we do not want to rotate the buffer. This change also adds effective_scaling_mode to winscope trace. Bug: b/74400997 Test: rotate the device with open gl test app provided in bug Test: open trace with winscope Test: mmma frameworks/native/services/surfaceflinger/tests/ && \ mmma frameworks/native/libs/gui/tests/ && adb sync data && \ adb shell /data/nativetest64/libgui_test/libgui_test && \ adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest && \ adb shell /data/nativetest64/SurfaceFlinger_test/SurfaceFlinger_test && \ adb shell /data/nativetest64/SurfaceParcelable_test/SurfaceParcelable_test && \ echo "ALL TESTS PASSED" Change-Id: Ibd181a4e8d2ec3a0ca9dc3c2900bb9dc2ac1ec0f --- services/surfaceflinger/Layer.cpp | 6 +++++- services/surfaceflinger/layerproto/layers.proto | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f29dfc0f1b..8bdd9165a5 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1337,7 +1337,10 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const { void Layer::updateTransformHint(const sp& display) const { uint32_t orientation = 0; - if (!mFlinger->mDebugDisableTransformHint) { + // Disable setting transform hint if the debug flag is set or if the + // getTransformToDisplayInverse flag is set and the client wants to submit buffers + // in one orientation. + if (!mFlinger->mDebugDisableTransformHint && !getTransformToDisplayInverse()) { // The transform hint is used to improve performance, but we can // only have a single transform hint, it cannot // apply to all displays. @@ -1969,6 +1972,7 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) layerInfo->set_window_type(state.type); layerInfo->set_app_id(state.appId); layerInfo->set_curr_frame(mCurrentFrameNumber); + layerInfo->set_effective_scaling_mode(getEffectiveScalingMode()); for (const auto& pendingState : mPendingStates) { auto barrierLayer = pendingState.barrierLayer_legacy.promote(); diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index 2a096345af..c141ee3cab 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -86,6 +86,7 @@ message LayerProto { repeated BarrierLayerProto barrier_layer = 38; // If active_buffer is not null, record its transform. optional TransformProto buffer_transform = 39; + optional int32 effective_scaling_mode = 40; } message PositionProto { -- cgit v1.2.3-59-g8ed1b From 6035634d8eef2adf5416ef751067a8e0dbbf7347 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Tue, 13 Nov 2018 13:00:45 -0800 Subject: SF: Add support for boundless layers 1/2 Size is currently used to bound a layer and its child layers. There are scenarios where we do not want to restrict a layer or its children to any specific size. For example 1. Have a color layer fill the bounds of its parent. 2. Have a layer apply a transform (ROTATION) to all child layers without cropping them. Currently this is achieved by providing a large enough size so that the layer or its children do not get cropped incorrectly. This change modifies computeBounds and computeScreenBounds to ignore a layer's size. We calculate the bounds by using the layer's buffer size and/or crop. Then we pass the bounds to the parent layer to crop to its bounds. If the layer has no bounds, we pass the child bounds forward. If we are also at the bottom of the hierarchy, such as a boundless color layer, then our bounds are set to the parent bounds. In WM, we set the layer's crop property in places where we relied on layer size. Bug: 114413815 Test: go/wm-smoke Test: mmma frameworks/native/services/surfaceflinger/tests/ && \ mmma frameworks/native/libs/gui/tests/ && adb sync data && \ adb shell /data/nativetest64/libgui_test/libgui_test && \ adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest && \ adb shell /data/nativetest64/SurfaceFlinger_test/SurfaceFlinger_test && \ adb shell /data/nativetest64/SurfaceParcelable_test/SurfaceParcelable_test && \ echo "ALL TESTS PASSED" Change-Id: I962c0c7639f6c863fc16b8acd16f077f040f8de4 --- services/surfaceflinger/BufferLayer.cpp | 30 +++ services/surfaceflinger/BufferLayer.h | 2 + services/surfaceflinger/BufferStateLayer.cpp | 6 +- services/surfaceflinger/Layer.cpp | 113 +++++----- services/surfaceflinger/Layer.h | 23 +- .../tests/SurfaceFlinger_test.filter | 2 +- services/surfaceflinger/tests/Transaction_test.cpp | 242 ++++++++++++++++++++- .../tests/unittests/CompositionTest.cpp | 3 + .../tests/unittests/TestableSurfaceFlinger.h | 1 + 9 files changed, 358 insertions(+), 64 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 440f1e24e1..52fbd440ff 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -667,6 +667,36 @@ uint64_t BufferLayer::getHeadFrameNumber() const { } } +Rect BufferLayer::getBufferSize(const State& s) const { + // If we have a sideband stream, or we are scaling the buffer then return the layer size since + // we cannot determine the buffer size. + if ((s.sidebandStream != nullptr) || + (getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE)) { + return Rect(getActiveWidth(s), getActiveHeight(s)); + } + + if (mActiveBuffer == nullptr) { + return Rect::INVALID_RECT; + } + + uint32_t bufWidth = mActiveBuffer->getWidth(); + uint32_t bufHeight = mActiveBuffer->getHeight(); + + // Undo any transformations on the buffer and return the result. + if (mCurrentTransform & ui::Transform::ROT_90) { + std::swap(bufWidth, bufHeight); + } + + if (getTransformToDisplayInverse()) { + uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); + if (invTransform & ui::Transform::ROT_90) { + std::swap(bufWidth, bufHeight); + } + } + + return Rect(bufWidth, bufHeight); +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index d000d85a2d..1d33a1f723 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -186,6 +186,8 @@ private: mutable renderengine::Texture mTexture; bool mRefreshPending{false}; + + Rect getBufferSize(const State& s) const override; }; } // namespace android diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 5df8ade34e..ac9e783556 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -35,7 +35,9 @@ const std::array BufferStateLayer::IDENTITY_MATRIX{ }; // clang-format on -BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) : BufferLayer(args) {} +BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) : BufferLayer(args) { + mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; +} BufferStateLayer::~BufferStateLayer() = default; // ----------------------------------------------------------------------- @@ -394,7 +396,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse } } - if (mOverrideScalingMode == NATIVE_WINDOW_SCALING_MODE_FREEZE && + if (getEffectiveScalingMode() == NATIVE_WINDOW_SCALING_MODE_FREEZE && (s.active.w != bufferWidth || s.active.h != bufferHeight)) { ALOGE("[%s] rejecting buffer: " "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}", diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 88c3c8a018..dba5f8f081 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -265,39 +265,12 @@ static FloatRect reduce(const FloatRect& win, const Region& exclude) { return Region(Rect{win}).subtract(exclude).getBounds().toFloatRect(); } -Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { - const State& s(getDrawingState()); - Rect win(getActiveWidth(s), getActiveHeight(s)); - - Rect crop = getCrop(s); - if (!crop.isEmpty()) { - win.intersect(crop, &win); - } - +Rect Layer::computeScreenBounds() const { + FloatRect bounds = computeBounds(); ui::Transform t = getTransform(); - win = t.transform(win); - - const sp& p = mDrawingParent.promote(); - // Now we need to calculate the parent bounds, so we can clip ourselves to those. - // When calculating the parent bounds for purposes of clipping, - // we don't need to constrain the parent to its transparent region. - // The transparent region is an optimization based on the - // buffer contents of the layer, but does not affect the space allocated to - // it by policy, and thus children should be allowed to extend into the - // parent's transparent region. In fact one of the main uses, is to reduce - // buffer allocation size in cases where a child window sits behind a main window - // (by marking the hole in the parent window as a transparent region) - if (p != nullptr) { - Rect bounds = p->computeScreenBounds(false); - bounds.intersect(win, &win); - } - - if (reduceTransparentRegion) { - auto const screenTransparentRegion = t.transform(getActiveTransparentRegion(s)); - win = reduce(win, screenTransparentRegion); - } - - return win; + // Transform to screen space. + bounds = t.transform(bounds); + return Rect{bounds}; } FloatRect Layer::computeBounds() const { @@ -307,32 +280,72 @@ FloatRect Layer::computeBounds() const { FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const { const State& s(getDrawingState()); - Rect win(getActiveWidth(s), getActiveHeight(s)); + Rect bounds = getCroppedBufferSize(s); + FloatRect floatBounds = bounds.toFloatRect(); + if (bounds.isValid()) { + // Layer has bounds. Pass in our bounds as a special case. Then pass on to our parents so + // that they can clip it. + floatBounds = cropChildBounds(floatBounds); + } else { + // Layer does not have bounds, so we fill to our parent bounds. This is done by getting our + // parent bounds and inverting the transform to get the maximum bounds we can have that + // will fit within our parent bounds. + const auto& p = mDrawingParent.promote(); + if (p != nullptr) { + ui::Transform t = s.active_legacy.transform; + // When calculating the parent bounds for purposes of clipping, we don't need to + // constrain the parent to its transparent region. The transparent region is an + // optimization based on the buffer contents of the layer, but does not affect the + // space allocated to it by policy, and thus children should be allowed to extend into + // the parent's transparent region. + // One of the main uses is a parent window with a child sitting behind the parent + // window, marked by a transparent region. When computing the parent bounds from the + // parent's perspective we pass in the transparent region to reduce buffer allocation + // size. When computing the parent bounds from the child's perspective, we pass in an + // empty transparent region in order to extend into the the parent bounds. + floatBounds = p->computeBounds(Region()); + // Transform back to layer space. + floatBounds = t.inverse().transform(floatBounds); + } + } - Rect crop = getCrop(s); - if (!crop.isEmpty()) { - win.intersect(crop, &win); + // Subtract the transparent region and snap to the bounds. + return reduce(floatBounds, activeTransparentRegion); +} + +FloatRect Layer::cropChildBounds(const FloatRect& childBounds) const { + const State& s(getDrawingState()); + Rect bounds = getCroppedBufferSize(s); + FloatRect croppedBounds = childBounds; + + // If the layer has bounds, then crop the passed in child bounds and pass + // it to our parents so they can crop it as well. If the layer has no bounds, + // then pass on the child bounds. + if (bounds.isValid()) { + croppedBounds = croppedBounds.intersect(bounds.toFloatRect()); } const auto& p = mDrawingParent.promote(); - FloatRect floatWin = win.toFloatRect(); - FloatRect parentBounds = floatWin; if (p != nullptr) { - // We pass an empty Region here for reasons mirroring that of the case described in - // the computeScreenBounds reduceTransparentRegion=false case. - parentBounds = p->computeBounds(Region()); + // Transform to parent space and allow parent layer to crop the + // child bounds as well. + ui::Transform t = s.active_legacy.transform; + croppedBounds = t.transform(croppedBounds); + croppedBounds = p->cropChildBounds(croppedBounds); + croppedBounds = t.inverse().transform(croppedBounds); } + return croppedBounds; +} - ui::Transform t = s.active_legacy.transform; - - if (p != nullptr) { - floatWin = t.transform(floatWin); - floatWin = floatWin.intersect(parentBounds); - floatWin = t.inverse().transform(floatWin); +Rect Layer::getCroppedBufferSize(const State& s) const { + Rect size = getBufferSize(s); + Rect crop = getCrop(s); + if (!crop.isEmpty() && size.isValid()) { + size.intersect(crop, &size); + } else if (!crop.isEmpty()) { + size = crop; } - - // subtract the transparent region and snap to the bounds - return reduce(floatWin, activeTransparentRegion); + return size; } Rect Layer::computeInitialCrop(const sp& display) const { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 5d05f0530b..21729ad9c7 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -575,7 +575,7 @@ public: ssize_t removeChild(const sp& layer); sp getParent() const { return mCurrentParent.promote(); } bool hasParent() const { return getParent() != nullptr; } - Rect computeScreenBounds(bool reduceTransparentRegion = true) const; + Rect computeScreenBounds() const; bool setChildLayer(const sp& childLayer, int32_t z); bool setChildRelativeLayer(const sp& childLayer, const sp& relativeToHandle, int32_t relativeZ); @@ -785,6 +785,27 @@ private: const LayerVector::Visitor& visitor); LayerVector makeChildrenTraversalList(LayerVector::StateSet stateSet, const std::vector& layersInTree); + + /** + * Retuns the child bounds in layer space cropped to its bounds as well all its parent bounds. + * The cropped bounds must be transformed back from parent layer space to child layer space by + * applying the inverse of the child's transformation. + */ + FloatRect cropChildBounds(const FloatRect& childBounds) const; + + /** + * Returns the cropped buffer size or the layer crop if the layer has no buffer. Return + * INVALID_RECT if the layer has no buffer and no crop. + * A layer with an invalid buffer size and no crop is considered to be boundless. The layer + * bounds are constrained by its parent bounds. + */ + Rect getCroppedBufferSize(const Layer::State& s) const; + + /** + * Returns active buffer size in the correct orientation. Buffer size is determined by undoing + * any buffer transformations. If the layer has no buffer then return INVALID_RECT. + */ + virtual Rect getBufferSize(const Layer::State&) const { return Rect::INVALID_RECT; } }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter index 8bd5fcbcc3..91999ae7f0 100644 --- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter +++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter @@ -1,5 +1,5 @@ { "presubmit": { - "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*" + "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*:BoundlessLayerTest.*" } } diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 3166a8c752..aed1f789af 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -328,10 +328,14 @@ protected: mClient->createSurface(String8(name), width, height, PIXEL_FORMAT_RGBA_8888, flags); EXPECT_NE(nullptr, layer.get()) << "failed to create SurfaceControl"; - status_t error = Transaction() - .setLayerStack(layer, mDisplayLayerStack) - .setLayer(layer, mLayerZBase) - .apply(); + Transaction t; + t.setLayerStack(layer, mDisplayLayerStack).setLayer(layer, mLayerZBase); + // If we are creating a color layer, set its crop since its size will be ignored. + if (flags == ISurfaceComposerClient::eFXSurfaceColor) { + t.setCrop_legacy(layer, Rect(0, 0, width, height)); + } + + status_t error = t.apply(); if (error != NO_ERROR) { ADD_FAILURE() << "failed to initialize SurfaceControl"; layer.clear(); @@ -495,6 +499,7 @@ private: // set layer stack (b/68888219) Transaction t; t.setDisplayLayerStack(mDisplay, mDisplayLayerStack); + t.setCrop_legacy(mBlackBgSurface, Rect(0, 0, mDisplayWidth, mDisplayHeight)); t.setLayerStack(mBlackBgSurface, mDisplayLayerStack); t.setColor(mBlackBgSurface, half3{0, 0, 0}); t.setLayer(mBlackBgSurface, mLayerZBase); @@ -2330,17 +2335,19 @@ TEST_F(LayerUpdateTest, LayerWithNoBuffersResizesImmediately) { mClient->createSurface(String8("Buffered child"), 20, 20, PIXEL_FORMAT_RGBA_8888, 0, childNoBuffer.get()); fillSurfaceRGBA8(childBuffer, 200, 200, 200); - - SurfaceComposerClient::Transaction{}.show(childNoBuffer).show(childBuffer).apply(true); - + SurfaceComposerClient::Transaction{} + .setCrop_legacy(childNoBuffer, Rect(0, 0, 10, 10)) + .show(childNoBuffer) + .show(childBuffer) + .apply(true); { ScreenCapture::captureScreen(&sc); sc->expectChildColor(73, 73); sc->expectFGColor(74, 74); } - - SurfaceComposerClient::Transaction{}.setSize(childNoBuffer, 20, 20).apply(true); - + SurfaceComposerClient::Transaction{} + .setCrop_legacy(childNoBuffer, Rect(0, 0, 20, 20)) + .apply(true); { ScreenCapture::captureScreen(&sc); sc->expectChildColor(73, 73); @@ -2844,6 +2851,221 @@ TEST_F(ChildLayerTest, ChildLayerRelativeLayer) { mCapture->checkPixel(10, 10, 255, 255, 255); } } +class BoundlessLayerTest : public LayerUpdateTest { +protected: + std::unique_ptr mCapture; +}; + +// Verify setting a size on a buffer layer has no effect. +TEST_F(BoundlessLayerTest, BufferLayerIgnoresSize) { + sp bufferLayer = + mClient->createSurface(String8("BufferLayer"), 45, 45, PIXEL_FORMAT_RGBA_8888, 0, + mFGSurfaceControl.get()); + ASSERT_TRUE(bufferLayer != nullptr); + ASSERT_TRUE(bufferLayer->isValid()); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::BLACK, 30, 30)); + asTransaction([&](Transaction& t) { t.show(bufferLayer); }); + { + mCapture = screenshot(); + // Top left of background must now be visible + mCapture->expectBGColor(0, 0); + // Foreground Surface bounds must be color layer + mCapture->expectColor(Rect(64, 64, 94, 94), Color::BLACK); + // Buffer layer should not extend past buffer bounds + mCapture->expectFGColor(95, 95); + } +} + +// Verify a boundless color layer will fill its parent bounds. The parent has a buffer size +// which will crop the color layer. +TEST_F(BoundlessLayerTest, BoundlessColorLayerFillsParentBufferBounds) { + sp colorLayer = + mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor, + mFGSurfaceControl.get()); + ASSERT_TRUE(colorLayer != nullptr); + ASSERT_TRUE(colorLayer->isValid()); + asTransaction([&](Transaction& t) { + t.setColor(colorLayer, half3{0, 0, 0}); + t.show(colorLayer); + }); + { + mCapture = screenshot(); + // Top left of background must now be visible + mCapture->expectBGColor(0, 0); + // Foreground Surface bounds must be color layer + mCapture->expectColor(Rect(64, 64, 128, 128), Color::BLACK); + // Color layer should not extend past foreground bounds + mCapture->expectBGColor(129, 129); + } +} + +// Verify a boundless color layer will fill its parent bounds. The parent has no buffer but has +// a crop which will be used to crop the color layer. +TEST_F(BoundlessLayerTest, BoundlessColorLayerFillsParentCropBounds) { + sp cropLayer = + mClient->createSurface(String8("CropLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, + 0 /* flags */, mFGSurfaceControl.get()); + ASSERT_TRUE(cropLayer != nullptr); + ASSERT_TRUE(cropLayer->isValid()); + sp colorLayer = + mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor, cropLayer.get()); + ASSERT_TRUE(colorLayer != nullptr); + ASSERT_TRUE(colorLayer->isValid()); + asTransaction([&](Transaction& t) { + t.setCrop_legacy(cropLayer, Rect(5, 5, 10, 10)); + t.setColor(colorLayer, half3{0, 0, 0}); + t.show(cropLayer); + t.show(colorLayer); + }); + { + mCapture = screenshot(); + // Top left of background must now be visible + mCapture->expectBGColor(0, 0); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // 5 pixels from the foreground we should see the child surface + mCapture->expectColor(Rect(69, 69, 74, 74), Color::BLACK); + // 10 pixels from the foreground we should be back to the foreground surface + mCapture->expectFGColor(74, 74); + } +} + +// Verify for boundless layer with no children, their transforms have no effect. +TEST_F(BoundlessLayerTest, BoundlessColorLayerTransformHasNoEffect) { + sp colorLayer = + mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor, + mFGSurfaceControl.get()); + ASSERT_TRUE(colorLayer != nullptr); + ASSERT_TRUE(colorLayer->isValid()); + asTransaction([&](Transaction& t) { + t.setPosition(colorLayer, 320, 320); + t.setMatrix(colorLayer, 2, 0, 0, 2); + t.setColor(colorLayer, half3{0, 0, 0}); + t.show(colorLayer); + }); + { + mCapture = screenshot(); + // Top left of background must now be visible + mCapture->expectBGColor(0, 0); + // Foreground Surface bounds must be color layer + mCapture->expectColor(Rect(64, 64, 128, 128), Color::BLACK); + // Color layer should not extend past foreground bounds + mCapture->expectBGColor(129, 129); + } +} + +// Verify for boundless layer with children, their transforms have an effect. +TEST_F(BoundlessLayerTest, IntermediateBoundlessLayerCanSetTransform) { + sp boundlessLayerRightShift = + mClient->createSurface(String8("BoundlessLayerRightShift"), 0, 0, + PIXEL_FORMAT_RGBA_8888, 0 /* flags */, mFGSurfaceControl.get()); + ASSERT_TRUE(boundlessLayerRightShift != nullptr); + ASSERT_TRUE(boundlessLayerRightShift->isValid()); + sp boundlessLayerDownShift = + mClient->createSurface(String8("BoundlessLayerLeftShift"), 0, 0, PIXEL_FORMAT_RGBA_8888, + 0 /* flags */, boundlessLayerRightShift.get()); + ASSERT_TRUE(boundlessLayerDownShift != nullptr); + ASSERT_TRUE(boundlessLayerDownShift->isValid()); + sp colorLayer = + mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor, + boundlessLayerDownShift.get()); + ASSERT_TRUE(colorLayer != nullptr); + ASSERT_TRUE(colorLayer->isValid()); + asTransaction([&](Transaction& t) { + t.setPosition(boundlessLayerRightShift, 32, 0); + t.show(boundlessLayerRightShift); + t.setPosition(boundlessLayerDownShift, 0, 32); + t.show(boundlessLayerDownShift); + t.setCrop_legacy(colorLayer, Rect(0, 0, 64, 64)); + t.setColor(colorLayer, half3{0, 0, 0}); + t.show(colorLayer); + }); + { + mCapture = screenshot(); + // Top left of background must now be visible + mCapture->expectBGColor(0, 0); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // Foreground Surface bounds must be color layer + mCapture->expectColor(Rect(96, 96, 128, 128), Color::BLACK); + // Color layer should not extend past foreground bounds + mCapture->expectBGColor(129, 129); + } +} + +// Verify child layers do not get clipped if they temporarily move into the negative +// coordinate space as the result of an intermediate transformation. +TEST_F(BoundlessLayerTest, IntermediateBoundlessLayerDoNotCrop) { + sp boundlessLayer = + mClient->createSurface(String8("BoundlessLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, + 0 /* flags */, mFGSurfaceControl.get()); + ASSERT_TRUE(boundlessLayer != nullptr); + ASSERT_TRUE(boundlessLayer->isValid()); + sp colorLayer = + mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor, boundlessLayer.get()); + ASSERT_TRUE(colorLayer != nullptr); + ASSERT_TRUE(colorLayer->isValid()); + asTransaction([&](Transaction& t) { + // shift child layer off bounds. If this layer was not boundless, we will + // expect the child layer to be cropped. + t.setPosition(boundlessLayer, 32, 32); + t.show(boundlessLayer); + t.setCrop_legacy(colorLayer, Rect(0, 0, 64, 64)); + // undo shift by parent + t.setPosition(colorLayer, -32, -32); + t.setColor(colorLayer, half3{0, 0, 0}); + t.show(colorLayer); + }); + { + mCapture = screenshot(); + // Top left of background must now be visible + mCapture->expectBGColor(0, 0); + // Foreground Surface bounds must be color layer + mCapture->expectColor(Rect(64, 64, 128, 128), Color::BLACK); + // Color layer should not extend past foreground bounds + mCapture->expectBGColor(129, 129); + } +} + +// Verify for boundless root layers with children, their transforms have an effect. +TEST_F(BoundlessLayerTest, RootBoundlessLayerCanSetTransform) { + sp rootBoundlessLayer = + mClient->createSurface(String8("RootBoundlessLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, + 0 /* flags */); + ASSERT_TRUE(rootBoundlessLayer != nullptr); + ASSERT_TRUE(rootBoundlessLayer->isValid()); + sp colorLayer = + mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor, + rootBoundlessLayer.get()); + ASSERT_TRUE(colorLayer != nullptr); + ASSERT_TRUE(colorLayer->isValid()); + asTransaction([&](Transaction& t) { + t.setLayer(rootBoundlessLayer, INT32_MAX - 1); + t.setPosition(rootBoundlessLayer, 32, 32); + t.show(rootBoundlessLayer); + t.setCrop_legacy(colorLayer, Rect(0, 0, 64, 64)); + t.setColor(colorLayer, half3{0, 0, 0}); + t.show(colorLayer); + t.hide(mFGSurfaceControl); + }); + { + mCapture = screenshot(); + // Top left of background must now be visible + mCapture->expectBGColor(0, 0); + // Top left of foreground must now be visible + mCapture->expectBGColor(31, 31); + // Foreground Surface bounds must be color layer + mCapture->expectColor(Rect(32, 32, 96, 96), Color::BLACK); + // Color layer should not extend past foreground bounds + mCapture->expectBGColor(97, 97); + } +} class ScreenCaptureTest : public LayerUpdateTest { protected: diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 3719a3d226..f71f1ea934 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -780,6 +780,9 @@ struct ColorLayerVariant : public BaseLayerVariant { LayerProperties::HEIGHT, LayerProperties::LAYER_FLAGS)); }); + + auto& layerDrawingState = test->mFlinger.mutableLayerDrawingState(layer); + layerDrawingState.crop_legacy = Rect(0, 0, LayerProperties::HEIGHT, LayerProperties::WIDTH); return layer; } diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 62afde9b0f..07cabd300c 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -61,6 +61,7 @@ public: auto& mutableLayerDrawingState(sp layer) { return layer->mDrawingState; } void setLayerSidebandStream(sp layer, sp sidebandStream) { + layer->mDrawingState.sidebandStream = sidebandStream; layer->getBE().compositionInfo.hwc.sidebandStream = sidebandStream; } -- cgit v1.2.3-59-g8ed1b From 341577629776c771ad2b4d9e0e452c34ed66ff0b Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Wed, 31 Oct 2018 13:07:19 -0700 Subject: SF: Define DisplayId as struct type This prevents accidental mix-up with HWC display IDs, which have the same backing type, as well as other implicitly convertible integers, e.g. EDID manufacturer IDs. This CL also fixes misuses detected by type checking: 1) Recycling of virtual display IDs. 2) Skipping composition for non-HWC virtual displays. 3) Unit tests for fallback/virtual display IDs. Bug: 74619554 Bug: 119412688 Test: libsurfaceflinger_unittest Test: vrflinger_test on walleye_xr Change-Id: I0be41cc93c82860e859f1adf427430436c926595 --- services/surfaceflinger/BufferLayer.cpp | 7 ++--- services/surfaceflinger/ColorLayer.cpp | 7 ++--- services/surfaceflinger/DisplayDevice.cpp | 2 +- .../DisplayHardware/DisplayIdentification.cpp | 22 +++++++++----- .../DisplayHardware/DisplayIdentification.h | 34 +++++++++++++++++++++- .../DisplayHardware/FramebufferSurface.cpp | 2 +- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 24 +++++++-------- .../surfaceflinger/DisplayHardware/HWComposer.h | 2 +- services/surfaceflinger/Layer.cpp | 30 ++++++------------- services/surfaceflinger/Layer.h | 13 +++++++-- services/surfaceflinger/SurfaceFlinger.cpp | 33 ++++++++++----------- services/surfaceflinger/SurfaceInterceptor.cpp | 2 +- .../tests/unittests/CompositionTest.cpp | 2 +- .../tests/unittests/DisplayTransactionTest.cpp | 10 +++---- 14 files changed, 109 insertions(+), 81 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 641bd8d1c3..6ef3aef5a5 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -231,15 +231,12 @@ bool BufferLayer::isHdrY410() const { void BufferLayer::setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport, int32_t supportedPerFrameMetadata) { + RETURN_IF_NO_HWC_LAYER(displayId); + // Apply this display's projection's viewport to the visible region // before giving it to the HWC HAL. Region visible = transform.transform(visibleRegion.intersect(viewport)); - if (!hasHwcLayer(displayId)) { - ALOGE("[%s] failed to setPerFrameData: no HWC layer found for display %" PRIu64, - mName.string(), displayId); - return; - } auto& hwcInfo = getBE().mHwcLayers[displayId]; auto& hwcLayer = hwcInfo.layer; auto error = hwcLayer->setVisibleRegion(visible); diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index ad716efa32..9c34308cab 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -59,13 +59,10 @@ bool ColorLayer::isVisible() const { void ColorLayer::setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport, int32_t /* supportedPerFrameMetadata */) { + RETURN_IF_NO_HWC_LAYER(displayId); + Region visible = transform.transform(visibleRegion.intersect(viewport)); - if (!hasHwcLayer(displayId)) { - ALOGE("[%s] failed to setPerFrameData: no HWC layer found for display %" PRIu64, - mName.string(), displayId); - return; - } auto& hwcInfo = getBE().mHwcLayers[displayId]; auto& hwcLayer = hwcInfo.layer; auto error = hwcLayer->setVisibleRegion(visible); diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 7c5c1bc8c3..071f07dc13 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -647,7 +647,7 @@ uint32_t DisplayDevice::getPrimaryDisplayOrientationTransform() { } std::string DisplayDevice::getDebugName() const { - const auto id = mId ? base::StringPrintf("%" PRIu64 ", ", *mId) : std::string(); + const auto id = mId ? to_string(*mId) + ", " : std::string(); return base::StringPrintf("DisplayDevice{%s%s%s\"%s\"}", id.c_str(), isPrimary() ? "primary, " : "", isVirtual() ? "virtual, " : "", mDisplayName.c_str()); diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp index ec240f3009..ba7818dd02 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp +++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp @@ -64,12 +64,16 @@ char getPnpLetter(uint16_t id) { return letter < 'A' || letter > 'Z' ? '\0' : letter; } -DisplayId getEdidDisplayId(uint8_t port, uint16_t manufacturerId, uint32_t displayNameHash) { - return (static_cast(manufacturerId) << 40) | - (static_cast(displayNameHash) << 8) | port; +} // namespace + +uint16_t DisplayId::manufacturerId() const { + return static_cast(value >> 40); } -} // namespace +DisplayId DisplayId::fromEdid(uint8_t port, uint16_t manufacturerId, uint32_t displayNameHash) { + return {(static_cast(manufacturerId) << 40) | (static_cast(displayNameHash) << 8) | + port}; +} bool isEdid(const DisplayIdentificationData& data) { const uint8_t kMagic[] = {0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0}; @@ -168,6 +172,10 @@ std::optional getPnpId(uint16_t manufacturerId) { return a && b && c ? std::make_optional(PnpId{a, b, c}) : std::nullopt; } +std::optional getPnpId(DisplayId displayId) { + return getPnpId(displayId.manufacturerId()); +} + std::optional parseDisplayIdentificationData( uint8_t port, const DisplayIdentificationData& data) { if (!isEdid(data)) { @@ -183,16 +191,16 @@ std::optional parseDisplayIdentificationData( // Hash display name instead of using product code or serial number, since the latter have been // observed to change on some displays with multiple inputs. const auto hash = static_cast(std::hash()(edid->displayName)); - return DisplayIdentificationInfo{getEdidDisplayId(port, edid->manufacturerId, hash), + return DisplayIdentificationInfo{DisplayId::fromEdid(port, edid->manufacturerId, hash), std::string(edid->displayName)}; } DisplayId getFallbackDisplayId(uint8_t port) { - return getEdidDisplayId(port, kFallbackEdidManufacturerId, 0); + return DisplayId::fromEdid(port, kFallbackEdidManufacturerId, 0); } DisplayId getVirtualDisplayId(uint32_t id) { - return getEdidDisplayId(0, kVirtualEdidManufacturerId, id); + return DisplayId::fromEdid(0, kVirtualEdidManufacturerId, id); } } // namespace android diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h index 1f2e789d13..1599995297 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h +++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h @@ -25,7 +25,27 @@ namespace android { -using DisplayId = uint64_t; +struct DisplayId { + using Type = uint64_t; + Type value; + + uint16_t manufacturerId() const; + + static DisplayId fromEdid(uint8_t port, uint16_t manufacturerId, uint32_t displayNameHash); +}; + +inline bool operator==(DisplayId lhs, DisplayId rhs) { + return lhs.value == rhs.value; +} + +inline bool operator!=(DisplayId lhs, DisplayId rhs) { + return !(lhs == rhs); +} + +inline std::string to_string(DisplayId displayId) { + return std::to_string(displayId.value); +} + using DisplayIdentificationData = std::vector; struct DisplayIdentificationInfo { @@ -45,6 +65,7 @@ struct Edid { bool isEdid(const DisplayIdentificationData&); std::optional parseEdid(const DisplayIdentificationData&); std::optional getPnpId(uint16_t manufacturerId); +std::optional getPnpId(DisplayId); std::optional parseDisplayIdentificationData( uint8_t port, const DisplayIdentificationData&); @@ -53,3 +74,14 @@ DisplayId getFallbackDisplayId(uint8_t port); DisplayId getVirtualDisplayId(uint32_t id); } // namespace android + +namespace std { + +template <> +struct hash { + size_t operator()(android::DisplayId displayId) const { + return hash()(displayId.value); + } +}; + +} // namespace std diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index f3f8d9d859..27812f7492 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -63,7 +63,7 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, DisplayId displayId, mHasPendingRelease(false), mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT), mPreviousBuffer() { - ALOGV("Creating for display %" PRIu64, displayId); + ALOGV("Creating for display %s", to_string(displayId).c_str()); mName = "FramebufferSurface"; mConsumer->setConsumerName(mName); diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 4c472b80ba..0f25b52f03 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -58,11 +58,11 @@ ALOGE("%s failed for HWC display %" PRIu64 ": %s", __FUNCTION__, hwcDisplayId, msg) #define LOG_DISPLAY_ERROR(displayId, msg) \ - ALOGE("%s failed for display %" PRIu64 ": %s", __FUNCTION__, displayId, msg) + ALOGE("%s failed for display %s: %s", __FUNCTION__, to_string(displayId).c_str(), msg) -#define LOG_HWC_ERROR(what, error, displayId) \ - ALOGE("%s: %s failed for display %" PRIu64 ": %s (%d)", __FUNCTION__, what, displayId, \ - to_string(error).c_str(), static_cast(error)) +#define LOG_HWC_ERROR(what, error, displayId) \ + ALOGE("%s: %s failed for display %s: %s (%d)", __FUNCTION__, what, \ + to_string(displayId).c_str(), to_string(error).c_str(), static_cast(error)) #define RETURN_IF_INVALID_DISPLAY(displayId, ...) \ do { \ @@ -159,9 +159,9 @@ std::optional HWComposer::onHotplug(hwc2_display_t hw if (!info) return {}; } - ALOGV("%s: %s %s display %" PRIu64 " with HWC ID %" PRIu64, __FUNCTION__, - to_string(connection).c_str(), - hwcDisplayId == mInternalHwcDisplayId ? "internal" : "external", info->id, hwcDisplayId); + ALOGV("%s: %s %s display %s with HWC ID %" PRIu64, __FUNCTION__, to_string(connection).c_str(), + hwcDisplayId == mInternalHwcDisplayId ? "internal" : "external", + to_string(info->id).c_str(), hwcDisplayId); mHwcDevice->onHotplug(hwcDisplayId, connection); @@ -198,15 +198,15 @@ bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) { // is a bug in the HWC implementation, but filter the extra events // out here so they don't cause havoc downstream. if (timestamp == mLastHwVSync[*displayId]) { - ALOGW("Ignoring duplicate VSYNC event from HWC for display %" PRIu64 " (t=%" PRId64 ")", - *displayId, timestamp); + ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")", + to_string(*displayId).c_str(), timestamp); return false; } mLastHwVSync[*displayId] = timestamp; } - const auto tag = "HW_VSYNC_" + std::to_string(*displayId); + const auto tag = "HW_VSYNC_" + to_string(*displayId); ATRACE_INT(tag.c_str(), ++mVSyncCounts[*displayId] & 1); return true; @@ -383,7 +383,7 @@ void HWComposer::setVsyncEnabled(DisplayId displayId, HWC2::Vsync enabled) { displayData.vsyncEnabled = enabled; - const auto tag = "HW_VSYNC_ON_" + std::to_string(displayId); + const auto tag = "HW_VSYNC_ON_" + to_string(displayId); ATRACE_INT(tag.c_str(), enabled == HWC2::Vsync::Enable ? 1 : 0); } } @@ -393,7 +393,7 @@ status_t HWComposer::setClientTarget(DisplayId displayId, uint32_t slot, ui::Dataspace dataspace) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); - ALOGV("setClientTarget for display %" PRIu64, displayId); + ALOGV("%s for display %s", __FUNCTION__, to_string(displayId).c_str()); auto& hwcDisplay = mDisplayData[displayId].hwcDisplay; auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace); RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE); diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 5074c2c49c..b78433dce4 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -233,7 +233,7 @@ private: cb_context* mCBContext = nullptr; std::unordered_map mVSyncCounts; - std::unordered_set mFreeVirtualDisplayIds; + std::unordered_set mFreeVirtualDisplayIds; uint32_t mNextVirtualDisplayId = 0; uint32_t mRemainingHwcVirtualDisplays{mHwcDevice->getMaxVirtualDisplayCount()}; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f41a753a7a..010a3392ff 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -197,8 +197,8 @@ sp Layer::getHandle() { // --------------------------------------------------------------------------- bool Layer::createHwcLayer(HWComposer* hwc, DisplayId displayId) { - LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(displayId) != 0, - "Already have a layer for display %" PRIu64, displayId); + LOG_ALWAYS_FATAL_IF(hasHwcLayer(displayId), "Already have a layer for display %s", + to_string(displayId).c_str()); auto layer = std::shared_ptr( hwc->createLayer(displayId), [hwc, displayId](HWC2::Layer* layer) { @@ -215,7 +215,7 @@ bool Layer::createHwcLayer(HWComposer* hwc, DisplayId displayId) { } bool Layer::destroyHwcLayer(DisplayId displayId) { - if (getBE().mHwcLayers.count(displayId) == 0) { + if (!hasHwcLayer(displayId)) { return false; } auto& hwcInfo = getBE().mHwcLayers[displayId]; @@ -462,11 +462,7 @@ FloatRect Layer::computeCrop(const sp& display) const { void Layer::setGeometry(const sp& display, uint32_t z) { const auto displayId = display->getId(); LOG_ALWAYS_FATAL_IF(!displayId); - if (!hasHwcLayer(*displayId)) { - ALOGE("[%s] failed to setGeometry: no HWC layer found for display %" PRIu64, mName.string(), - *displayId); - return; - } + RETURN_IF_NO_HWC_LAYER(*displayId); auto& hwcInfo = getBE().mHwcLayers[*displayId]; // enable this layer @@ -634,27 +630,19 @@ void Layer::setGeometry(const sp& display, uint32_t z) { } void Layer::forceClientComposition(DisplayId displayId) { - if (getBE().mHwcLayers.count(displayId) == 0) { - ALOGE("forceClientComposition: no HWC layer found (display %" PRIu64 ")", displayId); - return; - } - + RETURN_IF_NO_HWC_LAYER(displayId); getBE().mHwcLayers[displayId].forceClientComposition = true; } bool Layer::getForceClientComposition(DisplayId displayId) { - if (getBE().mHwcLayers.count(displayId) == 0) { - ALOGE("getForceClientComposition: no HWC layer found (display %" PRIu64 ")", displayId); - return false; - } - + RETURN_IF_NO_HWC_LAYER(displayId, false); return getBE().mHwcLayers[displayId].forceClientComposition; } void Layer::updateCursorPosition(const sp& display) { const auto displayId = display->getId(); - if (getBE().mHwcLayers.count(*displayId) == 0 || - getCompositionType(displayId) != HWC2::Composition::Cursor) { + LOG_ALWAYS_FATAL_IF(!displayId); + if (!hasHwcLayer(*displayId) || getCompositionType(displayId) != HWC2::Composition::Cursor) { return; } @@ -1422,7 +1410,7 @@ void Layer::miniDumpHeader(String8& result) { } void Layer::miniDump(String8& result, DisplayId displayId) const { - if (getBE().mHwcLayers.count(displayId) == 0) { + if (!hasHwcLayer(displayId)) { return; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ced6532505..8ce67c3b7b 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -499,7 +499,7 @@ public: bool destroyHwcLayer(DisplayId displayId); void destroyAllHwcLayers(); - bool hasHwcLayer(DisplayId displayId) { return getBE().mHwcLayers.count(displayId) > 0; } + bool hasHwcLayer(DisplayId displayId) const { return getBE().mHwcLayers.count(displayId) > 0; } HWC2::Layer* getHwcLayer(DisplayId displayId) { if (!hasHwcLayer(displayId)) { @@ -784,8 +784,15 @@ private: const std::vector& layersInTree); }; -// --------------------------------------------------------------------------- +} // namespace android -}; // namespace android +#define RETURN_IF_NO_HWC_LAYER(displayId, ...) \ + do { \ + if (!hasHwcLayer(displayId)) { \ + ALOGE("[%s] %s failed: no HWC layer found for display %s", mName.string(), \ + __FUNCTION__, to_string(displayId).c_str()); \ + return __VA_ARGS__; \ + } \ + } while (false) #endif // ANDROID_LAYER_H diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 368b9b8b59..26de7545df 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1043,9 +1043,9 @@ void SurfaceFlinger::setActiveColorModeInternal(const sp& display LOG_ALWAYS_FATAL_IF(!displayId); getHwComposer().setActiveColorMode(*displayId, mode, renderIntent); - ALOGV("Set active color mode: %s (%d), active render intent: %s (%d), display=%" PRIu64, + ALOGV("Set active color mode: %s (%d), active render intent: %s (%d), display=%s", decodeColorMode(mode).c_str(), mode, decodeRenderIntent(renderIntent).c_str(), - renderIntent, *displayId); + renderIntent, to_string(*displayId).c_str()); } status_t SurfaceFlinger::setActiveColorMode(const sp& displayToken, ColorMode mode) { @@ -1640,8 +1640,8 @@ void SurfaceFlinger::calculateWorkingSet() { display->setColorTransform(mDrawingState.colorMatrix); status_t result = getHwComposer().setColorTransform(*displayId, mDrawingState.colorMatrix); - ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display %" PRIu64 ": %d", - *displayId, result); + ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display %s: %d", + to_string(*displayId).c_str(), result); } for (auto& layer : display->getVisibleLayersSortedByZ()) { if (layer->isHdrY410()) { @@ -2275,7 +2275,7 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { if (event.connection == HWC2::Connection::Connected) { if (!mPhysicalDisplayTokens.count(info->id)) { - ALOGV("Creating display %" PRIu64, info->id); + ALOGV("Creating display %s", to_string(info->id).c_str()); mPhysicalDisplayTokens[info->id] = new BBinder(); DisplayDeviceState state; state.displayId = info->id; @@ -2285,7 +2285,7 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { mInterceptor->saveDisplayCreation(state); } } else { - ALOGV("Removing display %" PRIu64, info->id); + ALOGV("Removing display %s", to_string(info->id).c_str()); ssize_t index = mCurrentState.displays.indexOfKey(mPhysicalDisplayTokens[info->id]); if (index >= 0) { @@ -2978,8 +2978,7 @@ void SurfaceFlinger::doDisplayComposition(const sp& display // 1) It is being handled by hardware composer, which may need this to // keep its virtual display state machine in sync, or // 2) There is work to be done (the dirty region isn't empty) - bool isHwcDisplay = display->getId() >= 0; - if (!isHwcDisplay && inDirtyRegion.isEmpty()) { + if (!display->getId() && inDirtyRegion.isEmpty()) { ALOGV("Skipping display composition"); return; } @@ -3854,7 +3853,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp& display, int const auto displayId = display->getId(); LOG_ALWAYS_FATAL_IF(!displayId); - ALOGD("Setting power mode %d on display %" PRIu64, mode, *displayId); + ALOGD("Setting power mode %d on display %s", mode, to_string(*displayId).c_str()); int currentMode = display->getPowerMode(); if (mode == currentMode) { @@ -3953,7 +3952,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp& display, int mTimeStats.setPowerMode(mode); } - ALOGD("Finished setting power mode %d on display %" PRIu64, mode, *displayId); + ALOGD("Finished setting power mode %d on display %s", mode, to_string(*displayId).c_str()); } void SurfaceFlinger::setPowerMode(const sp& displayToken, int mode) { @@ -4284,7 +4283,7 @@ void SurfaceFlinger::dumpDisplayIdentificationData(String8& result) const { continue; } - result.appendFormat("Display %" PRIu64 " (HWC display %" PRIu64 "): ", *displayId, + result.appendFormat("Display %s (HWC display %" PRIu64 "): ", to_string(*displayId).c_str(), *hwcDisplayId); uint8_t port; DisplayIdentificationData data; @@ -4332,7 +4331,7 @@ void SurfaceFlinger::dumpWideColorInfo(String8& result) const { continue; } - result.appendFormat("Display %" PRIu64 " color modes:\n", *displayId); + result.appendFormat("Display %s color modes:\n", to_string(*displayId).c_str()); std::vector modes = getHwComposer().getColorModes(*displayId); for (auto&& mode : modes) { result.appendFormat(" %s (%d)\n", decodeColorMode(mode).c_str(), mode); @@ -4451,15 +4450,15 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, if (const auto displayId = getInternalDisplayId(); displayId && getHwComposer().isConnected(*displayId)) { const auto activeConfig = getHwComposer().getActiveConfig(*displayId); - result.appendFormat("Display %" PRIu64 ": app phase %" PRId64 " ns, " + result.appendFormat("Display %s: app phase %" PRId64 " ns, " "sf phase %" PRId64 " ns, " "early app phase %" PRId64 " ns, " "early sf phase %" PRId64 " ns, " "early app gl phase %" PRId64 " ns, " "early sf gl phase %" PRId64 " ns, " "present offset %" PRId64 " ns (refresh %" PRId64 " ns)", - *displayId, vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, appEarlyOffset, - sfEarlyOffset, appEarlyGlOffset, sfEarlyGlOffset, + to_string(*displayId).c_str(), vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, + appEarlyOffset, sfEarlyOffset, appEarlyGlOffset, sfEarlyGlOffset, dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod()); } result.append("\n"); @@ -4563,7 +4562,7 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, continue; } - result.appendFormat("Display %" PRIu64 " HWC layers:\n", *displayId); + result.appendFormat("Display %s HWC layers:\n", to_string(*displayId).c_str()); Layer::miniDumpHeader(result); mCurrentState.traverseInZOrder([&](Layer* layer) { layer->miniDump(result, *displayId); }); result.append("\n"); @@ -4604,7 +4603,7 @@ const Vector>& SurfaceFlinger::getLayerSortedByZForHwcDisplay(DisplayI } } - ALOGE("%s: Invalid display %" PRIu64, __FUNCTION__, displayId); + ALOGE("%s: Invalid display %s", __FUNCTION__, to_string(displayId).c_str()); static const Vector> empty; return empty; } diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 7faaff6ea6..55cfa4bf7d 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -497,7 +497,7 @@ void SurfaceInterceptor::addDisplayCreationLocked(Increment* increment, creation->set_name(info.displayName); creation->set_is_secure(info.isSecure); if (info.displayId) { - creation->set_display_id(*info.displayId); + creation->set_display_id(info.displayId->value); } } diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 09bb8c58f6..de6420e785 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -65,7 +65,7 @@ constexpr hwc2_display_t HWC_DISPLAY = FakeHwcDisplayInjector::DEFAULT_HWC_DISPL constexpr hwc2_layer_t HWC_LAYER = 5000; constexpr Transform DEFAULT_TRANSFORM = static_cast(0); -constexpr DisplayId DEFAULT_DISPLAY_ID = 42; +constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{42}; constexpr int DEFAULT_DISPLAY_WIDTH = 1920; constexpr int DEFAULT_DISPLAY_HEIGHT = 1024; diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index 2e90a59933..9d17ef45a1 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -249,8 +249,8 @@ const DisplayDeviceState& DisplayTransactionTest::getDrawingDisplayState(sp struct PhysicalDisplayId {}; -template -using VirtualDisplayId = std::integral_constant; +template +using VirtualDisplayId = std::integral_constant; struct NoDisplayId {}; @@ -279,9 +279,9 @@ struct DisplayIdGetter> { } }; -template +template struct DisplayIdGetter> { - static std::optional get() { return displayId; } + static std::optional get() { return DisplayId{displayId}; } }; template <> @@ -1090,7 +1090,7 @@ TEST_F(DisplayTransactionTest, resetDisplayStateClearsState) { */ class GetBestColorModeTest : public DisplayTransactionTest { public: - static constexpr DisplayId DEFAULT_DISPLAY_ID = 777; + static constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{777}; GetBestColorModeTest() : DisplayTransactionTest(), -- cgit v1.2.3-59-g8ed1b From 61626f2e8172ceea4e466eedf1e134d927f55b61 Mon Sep 17 00:00:00 2001 From: chaviw Date: Thu, 15 Nov 2018 16:26:27 -0800 Subject: Fixes for parentless layers 1. When a layer is removed, it needs to latch a buffer before the buffer can be released. 2. If a layer is removed from current state, it needs to get re-added back to current state when it gets reparented to a layer that is not removed from current state 3. If a layer is added as a child to a layer that has been removed from current state, the layer adding needs to succeed, but the layer needs to be automatically set as removed from current state. Bug: 111297488 Test: Test with updated ActivityView that has a SurfaceControl that has no reference in SF tree Change-Id: I8b723666964c61aaf7119b60ac256d19f85732b0 --- services/surfaceflinger/BufferLayer.cpp | 2 +- services/surfaceflinger/Layer.cpp | 22 +++++++++++++++++++--- services/surfaceflinger/Layer.h | 8 +++++++- services/surfaceflinger/SurfaceFlinger.cpp | 19 ++++++++++++++----- services/surfaceflinger/SurfaceFlinger.h | 1 + 5 files changed, 42 insertions(+), 10 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index ade62bf68f..d314942928 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -68,7 +68,7 @@ BufferLayer::~BufferLayer() { ALOGE("Found stale hardware composer layers when destroying " "surface flinger layer %s", mName.string()); - destroyAllHwcLayers(); + destroyAllHwcLayersPlusChildren(); } mTimeStats.onDestroy(getSequence()); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 038bc58a78..92a77b069c 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -123,7 +123,7 @@ Layer::~Layer() { mFrameTracker.logAndResetStats(mName); - destroyAllHwcLayers(); + destroyAllHwcLayersPlusChildren(); mFlinger->onLayerDestroyed(); } @@ -175,6 +175,14 @@ void Layer::onRemovedFromCurrentState() { } } +void Layer::addToCurrentState() { + mRemovedFromCurrentState = false; + + for (const auto& child : mCurrentChildren) { + child->addToCurrentState(); + } +} + // --------------------------------------------------------------------------- // set-up // --------------------------------------------------------------------------- @@ -226,17 +234,21 @@ bool Layer::destroyHwcLayer(DisplayId displayId) { return true; } -void Layer::destroyAllHwcLayers() { +void Layer::destroyHwcLayersForAllDisplays() { size_t numLayers = getBE().mHwcLayers.size(); for (size_t i = 0; i < numLayers; ++i) { LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.empty(), "destroyAllHwcLayers failed"); destroyHwcLayer(getBE().mHwcLayers.begin()->first); } +} + +void Layer::destroyAllHwcLayersPlusChildren() { + destroyHwcLayersForAllDisplays(); LOG_ALWAYS_FATAL_IF(!getBE().mHwcLayers.empty(), "All hardware composer layers should have been destroyed"); for (const sp& child : mDrawingChildren) { - child->destroyAllHwcLayers(); + child->destroyAllHwcLayersPlusChildren(); } } @@ -1587,6 +1599,10 @@ bool Layer::reparent(const sp& newParentHandle) { } newParent->addChild(this); + if (!newParent->isRemovedFromCurrentState()) { + addToCurrentState(); + } + sp client(mClientRef.promote()); sp newParentClient(newParent->mClientRef.promote()); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 40ebe1ed4d..2e19b8b1e7 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -485,6 +485,11 @@ public: */ void onRemovedFromCurrentState(); + /* + * Called when the layer is added back to the current state list. + */ + void addToCurrentState(); + // Updates the transform hint in our SurfaceFlingerConsumer to match // the current orientation of the display device. void updateTransformHint(const sp& display) const; @@ -506,7 +511,8 @@ public: bool createHwcLayer(HWComposer* hwc, DisplayId displayId); bool destroyHwcLayer(DisplayId displayId); - void destroyAllHwcLayers(); + void destroyHwcLayersForAllDisplays(); + void destroyAllHwcLayersPlusChildren(); bool hasHwcLayer(DisplayId displayId) const { return getBE().mHwcLayers.count(displayId) > 0; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 35ba39100d..43899e0635 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2717,6 +2717,17 @@ void SurfaceFlinger::updateCursorAsync() } } +void SurfaceFlinger::latchAndReleaseBuffer(const sp& layer) { + if (layer->hasReadyFrame()) { + const nsecs_t expectedPresentTime = mPrimaryDispSync->expectedPresentTime(); + if (layer->shouldPresentNow(expectedPresentTime)) { + bool ignored = false; + layer->latchBuffer(ignored, systemTime(), Fence::NO_FENCE); + } + } + layer->releasePendingBuffer(systemTime()); +} + void SurfaceFlinger::commitTransaction() { if (!mLayersPendingRemoval.isEmpty()) { @@ -2730,11 +2741,9 @@ void SurfaceFlinger::commitTransaction() // showing at its last configured state until we eventually // abandon the buffer queue. if (l->isRemovedFromCurrentState()) { - l->destroyAllHwcLayers(); - // destroyAllHwcLayers traverses to children, but releasePendingBuffer - // doesn't in other scenarios. So we have to traverse explicitly here. l->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* child) { - child->releasePendingBuffer(systemTime()); + child->destroyHwcLayersForAllDisplays(); + latchAndReleaseBuffer(child); }); } } @@ -3171,7 +3180,7 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, } else { if (parent->isRemovedFromCurrentState()) { ALOGE("addClientLayer called with a removed parent"); - return NAME_NOT_FOUND; + lbc->onRemovedFromCurrentState(); } parent->addChild(lbc); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 8b389bc624..d42536cc57 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -547,6 +547,7 @@ private: // Can only be called from the main thread or with mStateLock held uint32_t setTransactionFlags(uint32_t flags); uint32_t setTransactionFlags(uint32_t flags, Scheduler::TransactionStart transactionStart); + void latchAndReleaseBuffer(const sp& layer); void commitTransaction(); bool containsAnyInvalidClientState(const Vector& states); uint32_t setClientStateLocked(const ComposerState& composerState); -- cgit v1.2.3-59-g8ed1b From 5aedec95c3b10d24e2852d82078657a8e0f86874 Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 22 Oct 2018 10:40:38 -0700 Subject: Mark children as detached instead of actually detaching them. When detachChildren is called, mark children as detached instead of removing them from the client. This is so the children can be re-attached again when they're reparented. Check if layer is detached before copying currentState to drawingState so detached layers aren't updated. Also check if layer is detached before removing the layer since they should no longer be reachable if they're detached. Test: DetachChildrenThenAttach Bug: 111297488 Change-Id: I31b9eb1398f02e9d68dd3f7a1f231e1cef9fb0f8 --- services/surfaceflinger/Layer.cpp | 33 ++++++++++++- services/surfaceflinger/Layer.h | 6 ++- services/surfaceflinger/SurfaceFlinger.cpp | 4 ++ services/surfaceflinger/tests/Transaction_test.cpp | 55 ++++++++++++++++++++++ 4 files changed, 96 insertions(+), 2 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 1e910ced35..f3182be7cc 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1021,6 +1021,10 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { uint32_t Layer::doTransaction(uint32_t flags) { ATRACE_CALL(); + if (mLayerDetached) { + return 0; + } + pushPendingState(); State c = getCurrentState(); if (!applyPendingStates(&c)) { @@ -1553,6 +1557,9 @@ bool Layer::reparentChildren(const sp& newParentHandle) { return false; } + if (attachChildren()) { + setTransactionFlags(eTransactionNeeded); + } for (const sp& child : mCurrentChildren) { newParent->addChild(child); @@ -1597,6 +1604,13 @@ bool Layer::reparent(const sp& newParentHandle) { client->updateParent(newParent); } + if (mLayerDetached) { + mLayerDetached = false; + setTransactionFlags(eTransactionNeeded); + } + if (attachChildren()) { + setTransactionFlags(eTransactionNeeded); + } return true; } @@ -1605,7 +1619,7 @@ bool Layer::detachChildren() { sp parentClient = mClientRef.promote(); sp client(child->mClientRef.promote()); if (client != nullptr && parentClient != client) { - client->detachLayer(child.get()); + child->mLayerDetached = true; child->detachChildren(); } } @@ -1613,6 +1627,23 @@ bool Layer::detachChildren() { return true; } +bool Layer::attachChildren() { + bool changed = false; + for (const sp& child : mCurrentChildren) { + sp parentClient = mClientRef.promote(); + sp client(child->mClientRef.promote()); + if (client != nullptr && parentClient != client) { + if (child->mLayerDetached) { + child->mLayerDetached = false; + changed = true; + } + changed |= child->attachChildren(); + } + } + + return changed; +} + bool Layer::setColorTransform(const mat4& matrix) { static const mat4 identityMatrix = mat4(); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 40ebe1ed4d..ed51c61140 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -263,6 +263,8 @@ public: virtual void setChildrenDrawingParent(const sp& layer); virtual bool reparent(const sp& newParentHandle); virtual bool detachChildren(); + bool attachChildren(); + bool isLayerDetached() const { return mLayerDetached; } virtual bool setColorTransform(const mat4& matrix); virtual const mat4& getColorTransform() const; virtual bool hasColorTransform() const; @@ -355,7 +357,6 @@ public: // to avoid grabbing the lock again to avoid deadlock virtual bool isCreatedFromMainThread() const { return false; } - bool isRemovedFromCurrentState() const; void writeToProto(LayerProto* layerInfo, @@ -776,6 +777,9 @@ protected: mutable LayerBE mBE; + // Can only be accessed with the SF state lock held. + bool mLayerDetached{false}; + private: /** * Returns an unsorted vector of all layers that are part of this tree. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7150660278..2f5ee8af4e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3198,6 +3198,10 @@ status_t SurfaceFlinger::removeLayer(const sp& layer) { } status_t SurfaceFlinger::removeLayerLocked(const Mutex& lock, const sp& layer) { + if (layer->isLayerDetached()) { + return NO_ERROR; + } + const auto& p = layer->getParent(); ssize_t index; if (p != nullptr) { diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 988454ac94..a600a0a5af 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -3356,6 +3356,61 @@ TEST_F(ChildLayerTest, DetachChildrenDifferentClient) { } } +TEST_F(ChildLayerTest, DetachChildrenThenAttach) { + sp newComposerClient = new SurfaceComposerClient; + sp childNewClient = + newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + + ASSERT_TRUE(childNewClient != nullptr); + ASSERT_TRUE(childNewClient->isValid()); + + fillSurfaceRGBA8(childNewClient, 200, 200, 200); + + Transaction() + .hide(mChild) + .show(childNewClient) + .setPosition(childNewClient, 10, 10) + .setPosition(mFGSurfaceControl, 64, 64) + .apply(); + + { + mCapture = screenshot(); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // But 10 pixels in we should see the child surface + mCapture->expectChildColor(74, 74); + // And 10 more pixels we should be back to the foreground surface + mCapture->expectFGColor(84, 84); + } + + Transaction().detachChildren(mFGSurfaceControl).apply(); + Transaction().hide(childNewClient).apply(); + + // Nothing should have changed. + { + mCapture = screenshot(); + mCapture->expectFGColor(64, 64); + mCapture->expectChildColor(74, 74); + mCapture->expectFGColor(84, 84); + } + + sp newParentSurface = createLayer(String8("New Parent Surface"), 32, 32, 0); + fillLayerColor(ISurfaceComposerClient::eFXSurfaceBufferQueue, newParentSurface, Color::RED, 32, + 32); + Transaction() + .setLayer(newParentSurface, INT32_MAX - 1) + .show(newParentSurface) + .setPosition(newParentSurface, 20, 20) + .reparent(childNewClient, newParentSurface->getHandle()) + .apply(); + { + mCapture = screenshot(); + // Child is now hidden. + mCapture->expectColor(Rect(20, 20, 52, 52), Color::RED); + } +} + TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) { asTransaction([&](Transaction& t) { t.show(mChild); -- cgit v1.2.3-59-g8ed1b From 720e506fcab38d2f73b84630744ad100c5b6609d Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Mon, 30 Jul 2018 17:45:14 -0700 Subject: Forward input windows from SurfaceFlinger to InputDispatcher. We re-use values from visible region computation to fill in the frames, ensuring input always reflects the most recent state of the scene. Test: Extensive manual testing. Existing tests pass. Bug: 80101428 Bug: 113136004 Bug: 111440400 Change-Id: I9908a1bd6cba6abf16f2f6a43b6fe63f07a124a6 --- services/surfaceflinger/Android.bp | 2 ++ services/surfaceflinger/Layer.cpp | 30 ++++++++++++++++++++++++ services/surfaceflinger/Layer.h | 9 ++++++++ services/surfaceflinger/SurfaceFlinger.cpp | 37 +++++++++++++++++++++++++++++- services/surfaceflinger/SurfaceFlinger.h | 4 ++++ 5 files changed, 81 insertions(+), 1 deletion(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 088c2562b9..1007b3dc85 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -54,6 +54,7 @@ cc_defaults { "libsync", "libtimestats_proto", "libui", + "libinput", "libutils", ], static_libs: [ @@ -183,6 +184,7 @@ cc_defaults { "libdisplayservicehidl", "libhidlbase", "libhidltransport", + "libinput", "liblayers_proto", "liblog", "libsync", diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f3182be7cc..d9ec44a03e 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1057,6 +1057,11 @@ uint32_t Layer::doTransaction(uint32_t flags) { clearSyncPoints(); } + if (mCurrentState.inputInfoChanged) { + flags |= eInputInfoChanged; + mCurrentState.inputInfoChanged = false; + } + // Commit the transaction commitTransaction(c); mCurrentState.callbackHandles = {}; @@ -1928,6 +1933,13 @@ void Layer::commitChildList() { mDrawingParent = mCurrentParent; } +void Layer::setInputInfo(const InputWindowInfo& info) { + mCurrentState.inputInfo = info; + mCurrentState.modified = true; + mCurrentState.inputInfoChanged = true; + setTransactionFlags(eTransactionNeeded); +} + void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) { const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; @@ -2055,6 +2067,24 @@ bool Layer::isRemovedFromCurrentState() const { return mRemovedFromCurrentState; } +InputWindowInfo Layer::fillInputInfo(const Rect& screenBounds) { + InputWindowInfo info = mDrawingState.inputInfo; + info.frameLeft = screenBounds.left; + info.inputInfo.frameTop = screenBounds.top; + info.inputInfo.frameRight = screenBounds.right; + info.inputInfo.frameBottom = screenBounds.bottom; + + info.touchableRegion = mDrawingState.inputInfo.touchableRegion.translate( + screenBounds.left, + screenBounds.top); + info.visible = isVisible(); + return info; +} + +bool Layer::hasInput() const { + return mDrawingState.inputInfo.inputChannel != nullptr; +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ed51c61140..fe8d5a95c9 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -22,6 +22,7 @@ #include #include #include +#include