| Matvii Zorin | ef3c797 | 2020-08-11 15:15:44 +0300 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (C) 2020 The Android Open Source Project | 
|  | 3 | * | 
|  | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | * you may not use this file except in compliance with the License. | 
|  | 6 | * You may obtain a copy of the License at | 
|  | 7 | * | 
|  | 8 | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | * | 
|  | 10 | * Unless required by applicable law or agreed to in writing, software | 
|  | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | * See the License for the specific language governing permissions and | 
|  | 14 | * limitations under the License. | 
|  | 15 | */ | 
|  | 16 |  | 
| Roman Stratiienko | 13cc366 | 2020-08-29 21:35:39 +0300 | [diff] [blame] | 17 | #include "Backend.h" | 
|  | 18 |  | 
|  | 19 | #include "BackendManager.h" | 
| Matvii Zorin | ef3c797 | 2020-08-11 15:15:44 +0300 | [diff] [blame] | 20 |  | 
|  | 21 | namespace android { | 
|  | 22 |  | 
|  | 23 | HWC2::Error Backend::ValidateDisplay(DrmHwcTwo::HwcDisplay *display, | 
|  | 24 | uint32_t *num_types, | 
|  | 25 | uint32_t *num_requests) { | 
|  | 26 | *num_types = 0; | 
|  | 27 | *num_requests = 0; | 
|  | 28 | size_t avail_planes = display->primary_planes().size() + | 
|  | 29 | display->overlay_planes().size(); | 
|  | 30 |  | 
|  | 31 | /* | 
|  | 32 | * If more layers then planes, save one plane | 
|  | 33 | * for client composited layers | 
|  | 34 | */ | 
|  | 35 | if (avail_planes < display->layers().size()) | 
|  | 36 | avail_planes--; | 
|  | 37 |  | 
|  | 38 | std::map<uint32_t, DrmHwcTwo::HwcLayer *> z_map, z_map_tmp; | 
|  | 39 | uint32_t z_index = 0; | 
|  | 40 | // First create a map of layers and z_order values | 
|  | 41 | for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : | 
|  | 42 | display->layers()) | 
|  | 43 | z_map_tmp.emplace(std::make_pair(l.second.z_order(), &l.second)); | 
|  | 44 | // normalise the map so that the lowest z_order layer has key 0 | 
|  | 45 | for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map_tmp) | 
|  | 46 | z_map.emplace(std::make_pair(z_index++, l.second)); | 
|  | 47 |  | 
|  | 48 | uint32_t total_pixops = display->CalcPixOps(z_map, 0, z_map.size()); | 
|  | 49 | uint32_t gpu_pixops = 0; | 
|  | 50 |  | 
|  | 51 | int client_start = -1, client_size = 0; | 
|  | 52 |  | 
|  | 53 | if (display->compositor().ShouldFlattenOnClient()) { | 
|  | 54 | client_start = 0; | 
|  | 55 | client_size = z_map.size(); | 
|  | 56 | display->MarkValidated(z_map, client_start, client_size); | 
|  | 57 | } else { | 
|  | 58 | std::tie(client_start, client_size) = GetClientLayers(display, z_map); | 
|  | 59 |  | 
|  | 60 | int extra_client = (z_map.size() - client_size) - avail_planes; | 
|  | 61 | if (extra_client > 0) { | 
|  | 62 | int start = 0, steps; | 
|  | 63 | if (client_size != 0) { | 
|  | 64 | int prepend = std::min(client_start, extra_client); | 
|  | 65 | int append = std::min(int(z_map.size() - (client_start + client_size)), | 
|  | 66 | extra_client); | 
|  | 67 | start = client_start - prepend; | 
|  | 68 | client_size += extra_client; | 
|  | 69 | steps = 1 + std::min(std::min(append, prepend), | 
|  | 70 | int(z_map.size()) - (start + client_size)); | 
|  | 71 | } else { | 
|  | 72 | client_size = extra_client; | 
|  | 73 | steps = 1 + z_map.size() - extra_client; | 
|  | 74 | } | 
|  | 75 |  | 
|  | 76 | gpu_pixops = INT_MAX; | 
|  | 77 | for (int i = 0; i < steps; i++) { | 
|  | 78 | uint32_t po = display->CalcPixOps(z_map, start + i, client_size); | 
|  | 79 | if (po < gpu_pixops) { | 
|  | 80 | gpu_pixops = po; | 
|  | 81 | client_start = start + i; | 
|  | 82 | } | 
|  | 83 | } | 
|  | 84 | } | 
|  | 85 |  | 
|  | 86 | display->MarkValidated(z_map, client_start, client_size); | 
|  | 87 |  | 
|  | 88 | bool testing_needed = !(client_start == 0 && client_size == z_map.size()); | 
|  | 89 |  | 
|  | 90 | if (testing_needed && | 
|  | 91 | display->CreateComposition(true) != HWC2::Error::None) { | 
|  | 92 | ++display->total_stats().failed_kms_validate_; | 
|  | 93 | gpu_pixops = total_pixops; | 
|  | 94 | client_size = z_map.size(); | 
|  | 95 | display->MarkValidated(z_map, 0, client_size); | 
|  | 96 | } | 
|  | 97 | } | 
|  | 98 |  | 
|  | 99 | *num_types = client_size; | 
|  | 100 |  | 
|  | 101 | display->total_stats().frames_flattened_ = display->compositor() | 
|  | 102 | .GetFlattenedFramesCount(); | 
|  | 103 | display->total_stats().gpu_pixops_ += gpu_pixops; | 
|  | 104 | display->total_stats().total_pixops_ += total_pixops; | 
|  | 105 |  | 
|  | 106 | return *num_types ? HWC2::Error::HasChanges : HWC2::Error::None; | 
|  | 107 | } | 
|  | 108 |  | 
|  | 109 | std::tuple<int, int> Backend::GetClientLayers( | 
|  | 110 | DrmHwcTwo::HwcDisplay *display, | 
|  | 111 | const std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map) { | 
|  | 112 | int client_start = -1, client_size = 0; | 
|  | 113 |  | 
|  | 114 | for (auto & [ z_order, layer ] : z_map) { | 
|  | 115 | if (IsClientLayer(display, layer)) { | 
|  | 116 | if (client_start < 0) | 
|  | 117 | client_start = z_order; | 
|  | 118 | client_size = (z_order - client_start) + 1; | 
|  | 119 | } | 
|  | 120 | } | 
|  | 121 |  | 
|  | 122 | return std::make_tuple(client_start, client_size); | 
|  | 123 | } | 
|  | 124 |  | 
|  | 125 | bool Backend::IsClientLayer(DrmHwcTwo::HwcDisplay *display, | 
|  | 126 | DrmHwcTwo::HwcLayer *layer) { | 
|  | 127 | return !display->HardwareSupportsLayerType(layer->sf_type()) || | 
|  | 128 | !display->importer()->CanImportBuffer(layer->buffer()) || | 
|  | 129 | display->color_transform_hint() != HAL_COLOR_TRANSFORM_IDENTITY || | 
|  | 130 | (layer->RequireScalingOrPhasing() && | 
|  | 131 | display->resource_manager()->ForcedScalingWithGpu()); | 
|  | 132 | } | 
|  | 133 |  | 
|  | 134 | REGISTER_BACKEND("generic", Backend); | 
|  | 135 |  | 
|  | 136 | }  // namespace android |