blob: 08ee5a7c6ba747dd5461d666a4143c99c5ebebde [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
17#include "backend.h"
18#include "backendmanager.h"
19#include "drmhwctwo.h"
20
21namespace android {
22
23HWC2::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
109std::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
125bool 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
134REGISTER_BACKEND("generic", Backend);
135
136} // namespace android