blob: 196a893bf25b9a624d6f006f92333425b16adb66 [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();
49 display->MarkValidated(z_map, client_start, client_size);
50 } else {
51 std::tie(client_start, client_size) = GetClientLayers(display, z_map);
52
Matvii Zorinef3c7972020-08-11 15:15:44 +030053 display->MarkValidated(z_map, client_start, client_size);
54
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();
62 display->MarkValidated(z_map, 0, client_size);
63 }
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) {
96 return !display->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 Zorin2c91df52021-01-29 15:39:55 +0200103uint32_t Backend::CalcPixOps(const std::vector<DrmHwcTwo::HwcLayer *> &layers,
104 size_t first_z, size_t size) {
105 uint32_t pixops = 0;
106 for (auto & [ z_order, layer ] : z_map) {
107 if (z_order >= first_z && z_order < first_z + size) {
108 hwc_rect_t df = layer->display_frame();
109 pixops += (df.right - df.left) * (df.bottom - df.top);
110 }
111 }
112 return pixops;
113}
114
Matvii Zorinb3b15162021-01-29 15:48:20 +0200115std::tuple<int, int> Backend::GetExtraClientRange(
116 DrmHwcTwo::HwcDisplay *display,
117 const std::vector<DrmHwcTwo::HwcLayer *> &layers, int client_start,
118 size_t client_size) {
119 size_t avail_planes = display->primary_planes().size() +
120 display->overlay_planes().size();
121
122 /*
123 * If more layers then planes, save one plane
124 * for client composited layers
125 */
126 if (avail_planes < display->layers().size())
127 avail_planes--;
128
129 size_t extra_client = (layers.size() - client_size) - avail_planes;
130
131 if (extra_client > 0) {
132 int start = 0;
133 size_t steps = 0;
134 if (client_size != 0) {
135 size_t prepend = std::min((size_t)client_start, extra_client);
136 size_t append = std::min(layers.size() - (client_start + client_size),
137 extra_client);
138 start = client_start - (int)prepend;
139 client_size += extra_client;
140 steps = 1 + std::min(std::min(append, prepend),
141 int(z_map.size()) - (start + client_size));
142 } else {
143 client_size = extra_client;
144 steps = 1 + z_map.size() - extra_client;
145 }
146
147 uint32_t gpu_pixops = INT_MAX;
148 for (int i = 0; i < steps; i++) {
149 uint32_t po = CalcPixOps(z_map, start + i, client_size);
150 if (po < gpu_pixops) {
151 gpu_pixops = po;
152 client_start = start + i;
153 }
154 }
155 }
156
157 return std::make_tuple(client_start, client_size);
158}
159
Roman Stratiienkod21071f2021-03-09 21:56:50 +0200160// clang-format off
161// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp)
Matvii Zorinef3c7972020-08-11 15:15:44 +0300162REGISTER_BACKEND("generic", Backend);
Roman Stratiienkod21071f2021-03-09 21:56:50 +0200163// clang-format on
Matvii Zorinef3c7972020-08-11 15:15:44 +0300164
165} // namespace android