| /* |
| * 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 <layerproto/LayerProtoParser.h> |
| |
| namespace android { |
| namespace surfaceflinger { |
| bool sortLayers(const LayerProtoParser::Layer* lhs, const LayerProtoParser::Layer* rhs) { |
| uint32_t ls = lhs->layerStack; |
| uint32_t rs = rhs->layerStack; |
| if (ls != rs) return ls < rs; |
| |
| uint32_t lz = lhs->z; |
| uint32_t rz = rhs->z; |
| if (lz != rz) return lz < rz; |
| |
| return lhs->id < rhs->id; |
| } |
| |
| std::vector<const LayerProtoParser::Layer*> LayerProtoParser::generateLayerTree( |
| const LayersProto& layersProto) { |
| auto layerMap = generateMap(layersProto); |
| |
| std::vector<const Layer*> layers; |
| std::for_each(layerMap.begin(), layerMap.end(), |
| [&](const std::pair<const int32_t, Layer*>& ref) { |
| if (ref.second->parent == nullptr) { |
| // only save top level layers |
| layers.push_back(ref.second); |
| } |
| }); |
| |
| std::sort(layers.begin(), layers.end(), sortLayers); |
| return layers; |
| } |
| |
| std::unordered_map<int32_t, LayerProtoParser::Layer*> LayerProtoParser::generateMap( |
| const LayersProto& layersProto) { |
| std::unordered_map<int32_t, Layer*> layerMap; |
| |
| for (int i = 0; i < layersProto.layers_size(); i++) { |
| const LayerProto& layerProto = layersProto.layers(i); |
| layerMap[layerProto.id()] = generateLayer(layerProto); |
| } |
| |
| for (int i = 0; i < layersProto.layers_size(); i++) { |
| const LayerProto& layerProto = layersProto.layers(i); |
| updateChildrenAndRelative(layerProto, layerMap); |
| } |
| |
| return layerMap; |
| } |
| |
| LayerProtoParser::Layer* LayerProtoParser::generateLayer(const LayerProto& layerProto) { |
| Layer* layer = new Layer(); |
| layer->id = layerProto.id(); |
| layer->name = layerProto.name(); |
| layer->type = layerProto.type(); |
| layer->transparentRegion = generateRegion(layerProto.transparent_region()); |
| layer->visibleRegion = generateRegion(layerProto.visible_region()); |
| layer->damageRegion = generateRegion(layerProto.damage_region()); |
| layer->layerStack = layerProto.layer_stack(); |
| layer->z = layerProto.z(); |
| layer->position = {layerProto.position().x(), layerProto.position().y()}; |
| layer->requestedPosition = {layerProto.requested_position().x(), |
| 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(); |
| layer->pixelFormat = layerProto.pixel_format(); |
| layer->color = {layerProto.color().r(), layerProto.color().g(), layerProto.color().b(), |
| layerProto.color().a()}; |
| layer->requestedColor = {layerProto.requested_color().r(), layerProto.requested_color().g(), |
| layerProto.requested_color().b(), layerProto.requested_color().a()}; |
| layer->flags = layerProto.flags(); |
| layer->transform = generateTransform(layerProto.transform()); |
| layer->requestedTransform = generateTransform(layerProto.requested_transform()); |
| layer->activeBuffer = generateActiveBuffer(layerProto.active_buffer()); |
| layer->queuedFrames = layerProto.queued_frames(); |
| layer->refreshPending = layerProto.refresh_pending(); |
| |
| return layer; |
| } |
| |
| LayerProtoParser::Region LayerProtoParser::generateRegion(const RegionProto& regionProto) { |
| LayerProtoParser::Region region; |
| region.id = regionProto.id(); |
| for (int i = 0; i < regionProto.rect_size(); i++) { |
| const RectProto& rectProto = regionProto.rect(i); |
| region.rects.push_back(generateRect(rectProto)); |
| } |
| |
| return region; |
| } |
| |
| LayerProtoParser::Rect LayerProtoParser::generateRect(const RectProto& rectProto) { |
| LayerProtoParser::Rect 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; |
| transform.dsdx = transformProto.dsdx(); |
| transform.dtdx = transformProto.dtdx(); |
| transform.dsdy = transformProto.dsdy(); |
| transform.dtdy = transformProto.dtdy(); |
| |
| return transform; |
| } |
| |
| LayerProtoParser::ActiveBuffer LayerProtoParser::generateActiveBuffer( |
| const ActiveBufferProto& activeBufferProto) { |
| LayerProtoParser::ActiveBuffer activeBuffer; |
| activeBuffer.width = activeBufferProto.width(); |
| activeBuffer.height = activeBufferProto.height(); |
| activeBuffer.stride = activeBufferProto.stride(); |
| activeBuffer.format = activeBufferProto.format(); |
| |
| return activeBuffer; |
| } |
| |
| void LayerProtoParser::updateChildrenAndRelative(const LayerProto& layerProto, |
| std::unordered_map<int32_t, Layer*>& layerMap) { |
| auto currLayer = layerMap[layerProto.id()]; |
| |
| for (int i = 0; i < layerProto.children_size(); i++) { |
| if (layerMap.count(layerProto.children(i)) > 0) { |
| auto childLayer = layerMap[layerProto.children(i)]; |
| currLayer->children.push_back(childLayer); |
| } |
| } |
| |
| for (int i = 0; i < layerProto.relatives_size(); i++) { |
| if (layerMap.count(layerProto.relatives(i)) > 0) { |
| auto relativeLayer = layerMap[layerProto.relatives(i)]; |
| currLayer->relatives.push_back(relativeLayer); |
| } |
| } |
| |
| if (layerProto.has_parent()) { |
| if (layerMap.count(layerProto.parent()) > 0) { |
| auto parentLayer = layerMap[layerProto.parent()]; |
| currLayer->parent = parentLayer; |
| } |
| } |
| |
| if (layerProto.has_z_order_relative_of()) { |
| if (layerMap.count(layerProto.z_order_relative_of()) > 0) { |
| auto relativeLayer = layerMap[layerProto.z_order_relative_of()]; |
| currLayer->zOrderRelativeOf = relativeLayer; |
| } |
| } |
| } |
| |
| std::string LayerProtoParser::layersToString( |
| const std::vector<const LayerProtoParser::Layer*> layers) { |
| std::string result; |
| for (const LayerProtoParser::Layer* layer : layers) { |
| if (layer->zOrderRelativeOf != nullptr) { |
| continue; |
| } |
| result.append(layerToString(layer).c_str()); |
| } |
| |
| return result; |
| } |
| |
| std::string LayerProtoParser::layerToString(const LayerProtoParser::Layer* layer) { |
| std::string result; |
| |
| std::vector<const Layer*> traverse(layer->relatives); |
| for (const LayerProtoParser::Layer* child : layer->children) { |
| if (child->zOrderRelativeOf != nullptr) { |
| continue; |
| } |
| |
| traverse.push_back(child); |
| } |
| |
| std::sort(traverse.begin(), traverse.end(), sortLayers); |
| |
| size_t i = 0; |
| for (; i < traverse.size(); i++) { |
| const auto& relative = traverse[i]; |
| if (relative->z >= 0) { |
| break; |
| } |
| result.append(layerToString(relative).c_str()); |
| } |
| result.append(layer->to_string().c_str()); |
| result.append("\n"); |
| for (; i < traverse.size(); i++) { |
| const auto& relative = traverse[i]; |
| result.append(layerToString(relative).c_str()); |
| } |
| |
| return result; |
| } |
| |
| } // namespace surfaceflinger |
| } // namespace android |