blob: 4c2a93129304b0eafd5732a0dde1a30318019883 [file] [log] [blame]
Matvii Zorinef3c7972020-08-11 15:15:44 +03001/*
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 Stratiienko13cc3662020-08-29 21:35:39 +030017#include "Backend.h"
18
Roman Stratiienkod21071f2021-03-09 21:56:50 +020019#include <climits>
20
Roman Stratiienko13cc3662020-08-29 21:35:39 +030021#include "BackendManager.h"
Roman Stratiienkob2e9fe22020-10-03 10:52:36 +030022#include "bufferinfo/BufferInfoGetter.h"
Matvii Zorinef3c7972020-08-11 15:15:44 +030023
24namespace android {
25
26HWC2::Error Backend::ValidateDisplay(DrmHwcTwo::HwcDisplay *display,
27 uint32_t *num_types,
28 uint32_t *num_requests) {
29 *num_types = 0;
30 *num_requests = 0;
Matvii Zorinef3c7972020-08-11 15:15:44 +030031
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020032 std::map<uint32_t, DrmHwcTwo::HwcLayer *> z_map;
33 std::map<uint32_t, DrmHwcTwo::HwcLayer *> z_map_tmp;
Matvii Zorinef3c7972020-08-11 15:15:44 +030034 uint32_t z_index = 0;
35 // First create a map of layers and z_order values
36 for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l :
37 display->layers())
38 z_map_tmp.emplace(std::make_pair(l.second.z_order(), &l.second));
39 // normalise the map so that the lowest z_order layer has key 0
40 for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map_tmp)
41 z_map.emplace(std::make_pair(z_index++, l.second));
42
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020043 int client_start = -1;
44 size_t client_size = 0;
Matvii Zorinef3c7972020-08-11 15:15:44 +030045
46 if (display->compositor().ShouldFlattenOnClient()) {
47 client_start = 0;
48 client_size = z_map.size();
Matvii Zorined745272021-01-29 16:40:25 +020049 MarkValidated(z_map, client_start, client_size);
Matvii Zorinef3c7972020-08-11 15:15:44 +030050 } else {
51 std::tie(client_start, client_size) = GetClientLayers(display, z_map);
52
Matvii Zorined745272021-01-29 16:40:25 +020053 MarkValidated(z_map, client_start, client_size);
Matvii Zorinef3c7972020-08-11 15:15:44 +030054
55 bool testing_needed = !(client_start == 0 && client_size == z_map.size());
56
57 if (testing_needed &&
58 display->CreateComposition(true) != HWC2::Error::None) {
59 ++display->total_stats().failed_kms_validate_;
Matvii Zorinb3b15162021-01-29 15:48:20 +020060 client_start = 0;
Matvii Zorinef3c7972020-08-11 15:15:44 +030061 client_size = z_map.size();
Matvii Zorined745272021-01-29 16:40:25 +020062 MarkValidated(z_map, 0, client_size);
Matvii Zorinef3c7972020-08-11 15:15:44 +030063 }
64 }
65
66 *num_types = client_size;
67
68 display->total_stats().frames_flattened_ = display->compositor()
69 .GetFlattenedFramesCount();
Matvii Zorinb3b15162021-01-29 15:48:20 +020070 display->total_stats().gpu_pixops_ += CalcPixOps(z_map, client_start,
71 client_size);
72 display->total_stats().total_pixops_ += CalcPixOps(z_map, 0, z_map.size());
Matvii Zorinef3c7972020-08-11 15:15:44 +030073
74 return *num_types ? HWC2::Error::HasChanges : HWC2::Error::None;
75}
76
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020077std::tuple<int, size_t> Backend::GetClientLayers(
Matvii Zorinef3c7972020-08-11 15:15:44 +030078 DrmHwcTwo::HwcDisplay *display,
Matvii Zorinb3b15162021-01-29 15:48:20 +020079 const std::vector<DrmHwcTwo::HwcLayer *> &layers) {
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020080 int client_start = -1;
81 size_t client_size = 0;
Matvii Zorinef3c7972020-08-11 15:15:44 +030082
Roman Stratiienkod21071f2021-03-09 21:56:50 +020083 for (const auto &[z_order, layer] : z_map) {
Matvii Zorinef3c7972020-08-11 15:15:44 +030084 if (IsClientLayer(display, layer)) {
85 if (client_start < 0)
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020086 client_start = (int)z_order;
Matvii Zorinef3c7972020-08-11 15:15:44 +030087 client_size = (z_order - client_start) + 1;
88 }
89 }
90
Matvii Zorinb3b15162021-01-29 15:48:20 +020091 return GetExtraClientRange(display, z_map, client_start, client_size);
Matvii Zorinef3c7972020-08-11 15:15:44 +030092}
93
94bool Backend::IsClientLayer(DrmHwcTwo::HwcDisplay *display,
95 DrmHwcTwo::HwcLayer *layer) {
Matvii Zorinede54b02021-01-29 16:45:25 +020096 return !HardwareSupportsLayerType(layer->sf_type()) ||
Roman Stratiienkob2e9fe22020-10-03 10:52:36 +030097 !BufferInfoGetter::GetInstance()->IsHandleUsable(layer->buffer()) ||
Matvii Zorinef3c7972020-08-11 15:15:44 +030098 display->color_transform_hint() != HAL_COLOR_TRANSFORM_IDENTITY ||
99 (layer->RequireScalingOrPhasing() &&
100 display->resource_manager()->ForcedScalingWithGpu());
101}
102
Matvii Zorinede54b02021-01-29 16:45:25 +0200103bool Backend::HardwareSupportsLayerType(HWC2::Composition comp_type) {
104 return comp_type == HWC2::Composition::Device ||
105 comp_type == HWC2::Composition::Cursor;
106}
107
Matvii Zorin2c91df52021-01-29 15:39:55 +0200108uint32_t Backend::CalcPixOps(const std::vector<DrmHwcTwo::HwcLayer *> &layers,
109 size_t first_z, size_t size) {
110 uint32_t pixops = 0;
111 for (auto & [ z_order, layer ] : z_map) {
112 if (z_order >= first_z && z_order < first_z + size) {
113 hwc_rect_t df = layer->display_frame();
114 pixops += (df.right - df.left) * (df.bottom - df.top);
115 }
116 }
117 return pixops;
118}
119
Matvii Zorined745272021-01-29 16:40:25 +0200120void Backend::MarkValidated(std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map,
121 size_t client_first_z, size_t client_size) {
122 for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) {
123 if (l.first >= client_first_z && l.first < client_first_z + client_size)
124 l.second->set_validated_type(HWC2::Composition::Client);
125 else
126 l.second->set_validated_type(HWC2::Composition::Device);
127 }
128}
129
Matvii Zorinb3b15162021-01-29 15:48:20 +0200130std::tuple<int, int> Backend::GetExtraClientRange(
131 DrmHwcTwo::HwcDisplay *display,
132 const std::vector<DrmHwcTwo::HwcLayer *> &layers, int client_start,
133 size_t client_size) {
134 size_t avail_planes = display->primary_planes().size() +
135 display->overlay_planes().size();
136
137 /*
138 * If more layers then planes, save one plane
139 * for client composited layers
140 */
141 if (avail_planes < display->layers().size())
142 avail_planes--;
143
144 size_t extra_client = (layers.size() - client_size) - avail_planes;
145
146 if (extra_client > 0) {
147 int start = 0;
148 size_t steps = 0;
149 if (client_size != 0) {
150 size_t prepend = std::min((size_t)client_start, extra_client);
151 size_t append = std::min(layers.size() - (client_start + client_size),
152 extra_client);
153 start = client_start - (int)prepend;
154 client_size += extra_client;
155 steps = 1 + std::min(std::min(append, prepend),
156 int(z_map.size()) - (start + client_size));
157 } else {
158 client_size = extra_client;
159 steps = 1 + z_map.size() - extra_client;
160 }
161
162 uint32_t gpu_pixops = INT_MAX;
163 for (int i = 0; i < steps; i++) {
164 uint32_t po = CalcPixOps(z_map, start + i, client_size);
165 if (po < gpu_pixops) {
166 gpu_pixops = po;
167 client_start = start + i;
168 }
169 }
170 }
171
172 return std::make_tuple(client_start, client_size);
173}
174
Roman Stratiienkod21071f2021-03-09 21:56:50 +0200175// clang-format off
176// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp)
Matvii Zorinef3c7972020-08-11 15:15:44 +0300177REGISTER_BACKEND("generic", Backend);
Roman Stratiienkod21071f2021-03-09 21:56:50 +0200178// clang-format on
Matvii Zorinef3c7972020-08-11 15:15:44 +0300179
180} // namespace android