From 1d04428c3cff3503212ec3e76775ca5ba20abc18 Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 27 Sep 2017 12:19:28 -0700 Subject: Added protobuf to gather layer info. Use protobuf to gather information about the layers. This change also uses protobuf for the layer dumpsys. Test: Ran dumpsys for layers to confirm the data was correct. Change-Id: Iec474e57a4fb9de1e548440d6a08685505947278 --- services/surfaceflinger/LayerProtoHelper.cpp | 63 ++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 services/surfaceflinger/LayerProtoHelper.cpp (limited to 'services/surfaceflinger/LayerProtoHelper.cpp') diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp new file mode 100644 index 0000000000..6a33148d27 --- /dev/null +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -0,0 +1,63 @@ +/* + * 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 "LayerProtoHelper.h" + +namespace android { +namespace surfaceflinger { +void LayerProtoHelper::writeToProto(const Region& region, RegionProto* regionProto) { + Region::const_iterator head = region.begin(); + Region::const_iterator const tail = region.end(); + uint64_t address = reinterpret_cast(®ion); + regionProto->set_id(address); + while (head != tail) { + RectProto* rectProto = regionProto->add_rect(); + writeToProto(*head, rectProto); + head++; + } +} + +void LayerProtoHelper::writeToProto(const Rect& rect, RectProto* 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); + colorProto->set_b(color.b); + colorProto->set_a(color.a); +} + +void LayerProtoHelper::writeToProto(const Transform& transform, TransformProto* transformProto) { + transformProto->set_dsdx(transform[0][0]); + transformProto->set_dtdx(transform[0][1]); + transformProto->set_dsdy(transform[1][0]); + transformProto->set_dtdy(transform[1][1]); +} + +void LayerProtoHelper::writeToProto(const sp& buffer, + ActiveBufferProto* activeBufferProto) { + activeBufferProto->set_width(buffer->getWidth()); + activeBufferProto->set_height(buffer->getHeight()); + activeBufferProto->set_stride(buffer->getStride()); + activeBufferProto->set_format(buffer->format); +} + +} // namespace surfaceflinger +} // namespace android -- cgit v1.2.3-59-g8ed1b From 068e31b929b40a1bc9be742c04cbdf5b04f3ce97 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 Change-Id: Ie08aa85d34db2c2c767b8e27eb5aad6f7c3fb975 Merged-In: Ie08aa85d34db2c2c767b8e27eb5aad6f7c3fb975 --- services/surfaceflinger/Android.bp | 1 + services/surfaceflinger/Layer.cpp | 16 ++ services/surfaceflinger/Layer.h | 6 +- services/surfaceflinger/LayerProtoHelper.cpp | 7 + services/surfaceflinger/LayerProtoHelper.h | 3 +- services/surfaceflinger/LayerStats.cpp | 181 +++++++++++++++++++++ services/surfaceflinger/LayerStats.h | 69 ++++++++ services/surfaceflinger/SurfaceFlinger.cpp | 67 ++++++++ services/surfaceflinger/SurfaceFlinger.h | 4 + .../surfaceflinger/layerproto/LayerProtoParser.cpp | 22 +++ .../include/layerproto/LayerProtoParser.h | 21 +++ services/surfaceflinger/layerproto/layers.proto | 20 ++- 12 files changed, 412 insertions(+), 5 deletions(-) create mode 100644 services/surfaceflinger/LayerStats.cpp create mode 100644 services/surfaceflinger/LayerStats.h (limited to 'services/surfaceflinger/LayerProtoHelper.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index ba28eb5298..ff994f515c 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -105,6 +105,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 166ac22fa2..c3eb1bc85f 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -635,6 +635,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: " @@ -1923,6 +1924,21 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) layerInfo->set_app_id(state.appId); } +void Layer::writeToProto(LayerProto* layerInfo, int32_t hwcId) { + writeToProto(layerInfo, LayerVector::StateSet::Drawing); + + const auto& hwcInfo = getBE().mHwcLayers.at(hwcId); + + const Rect& frame = hwcInfo.displayFrame; + LayerProtoHelper::writeToProto(frame, layerInfo->mutable_hwc_frame()); + + const FloatRect& crop = hwcInfo.sourceCrop; + LayerProtoHelper::writeToProto(crop, layerInfo->mutable_hwc_crop()); + + const int32_t transform = static_cast(hwcInfo.transform); + layerInfo->set_hwc_transform(transform); +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 9a9b5e60c8..69ffb2018c 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -113,7 +113,8 @@ public: layer(nullptr), forceClientComposition(false), compositionType(HWC2::Composition::Invalid), - clearClientTarget(false) {} + clearClientTarget(false), + transform(HWC2::Transform::None) {} HWComposer* hwc; HWC2::Layer* layer; @@ -123,6 +124,7 @@ public: Rect displayFrame; FloatRect sourceCrop; HWComposerBufferCache bufferCache; + HWC2::Transform transform; }; // A layer can be attached to multiple displays when operating in mirror mode @@ -357,6 +359,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/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..dc99b41cc6 --- /dev/null +++ b/services/surfaceflinger/LayerStats.cpp @@ -0,0 +1,181 @@ +/* + * 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( + std::vector> layerTree, + const LayerProtoParser::LayerGlobal* layerGlobal) { + 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]++; + } +} + +void LayerStats::logLayerStats(const LayersProto& layersProto) { + ATRACE_CALL(); + auto layerGlobal = LayerProtoParser::generateLayerGlobalInfo(layersProto); + auto layerTree = LayerProtoParser::generateLayerTree(layersProto); + std::lock_guard lock(mMutex); + traverseLayerTreeStatsLocked(std::move(layerTree), &layerGlobal); +} + +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..de2b47c3ba --- /dev/null +++ b/services/surfaceflinger/LayerStats.h @@ -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. + */ + +#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( + 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 f180a3b285..babac37d7d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1484,6 +1484,7 @@ void SurfaceFlinger::handleMessageRefresh() { setUpHWComposer(); doDebugFlashRegions(); doTracing("handleRefresh"); + logLayerStats(); doComposition(); postComposition(refreshStartTime); @@ -1553,6 +1554,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(); @@ -3772,6 +3792,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) { @@ -3979,6 +4027,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 448509bc8f..c7c308883b 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -55,6 +55,7 @@ #include "DisplayDevice.h" #include "DispSync.h" #include "FrameTracker.h" +#include "LayerStats.h" #include "LayerVector.h" #include "MessageQueue.h" #include "SurfaceInterceptor.h" @@ -645,6 +646,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 @@ -711,6 +713,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; @@ -797,6 +800,7 @@ private: std::unique_ptr mInterceptor = std::make_unique(this); 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 1383d288b9..cef6c21eb1 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -42,6 +42,11 @@ bool sortLayerUniquePtrs(const std::unique_ptr& lhs, return sortLayers(lhs.get(), rhs.get()); } +const LayerProtoParser::LayerGlobal LayerProtoParser::generateLayerGlobalInfo( + const LayersProto& layersProto) { + return {{layersProto.resolution().w(), layersProto.resolution().h()}}; +} + std::vector> LayerProtoParser::generateLayerTree( const LayersProto& layersProto) { std::unordered_map layerMap = generateMap(layersProto); @@ -106,6 +111,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(); layer->windowType = layerProto.window_type(); layer->appId = layerProto.app_id(); @@ -133,6 +141,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; @@ -246,6 +264,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 b56a6fbb97..fd893da1b1 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 @@ -57,6 +58,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; @@ -96,12 +107,21 @@ public: LayerProtoParser::ActiveBuffer activeBuffer; int32_t queuedFrames; bool refreshPending; + LayerProtoParser::Rect hwcFrame; + LayerProtoParser::FloatRect hwcCrop; + int32_t hwcTransform; int32_t windowType; int32_t appId; 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 std::string layersToString(std::vector> layers); @@ -110,6 +130,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 f18386b1ac..6675aae797 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,8 +65,14 @@ message LayerProto { // The number of frames available. optional int32 queued_frames = 28; optional bool refresh_pending = 29; - optional int32 window_type = 30; - optional int32 app_id = 31; + // 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; + optional int32 window_type = 33; + optional int32 app_id = 34; } message PositionProto { @@ -97,6 +104,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; @@ -109,4 +123,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