OSDN Git Service

drm_hwcomposer: Add GetOrderLayersByZPos method
[android-x86/external-drm_hwcomposer.git] / backend / Backend.cpp
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
17 #include "Backend.h"
18
19 #include <climits>
20
21 #include "BackendManager.h"
22 #include "bufferinfo/BufferInfoGetter.h"
23
24 namespace android {
25
26 HWC2::Error Backend::ValidateDisplay(DrmHwcTwo::HwcDisplay *display,
27                                      uint32_t *num_types,
28                                      uint32_t *num_requests) {
29   *num_types = 0;
30   *num_requests = 0;
31
32   auto layers = display->GetOrderLayersByZPos();
33
34   int client_start = -1;
35   size_t client_size = 0;
36
37   if (display->compositor().ShouldFlattenOnClient()) {
38     client_start = 0;
39     client_size = layers.size();
40     MarkValidated(layers, client_start, client_size);
41   } else {
42     std::tie(client_start, client_size) = GetClientLayers(display, layers);
43
44     MarkValidated(layers, client_start, client_size);
45
46     bool testing_needed = !(client_start == 0 && client_size == layers.size());
47
48     if (testing_needed &&
49         display->CreateComposition(true) != HWC2::Error::None) {
50       ++display->total_stats().failed_kms_validate_;
51       client_start = 0;
52       client_size = layers.size();
53       MarkValidated(layers, 0, client_size);
54     }
55   }
56
57   *num_types = client_size;
58
59   display->total_stats().frames_flattened_ = display->compositor()
60                                                  .GetFlattenedFramesCount();
61   display->total_stats().gpu_pixops_ += CalcPixOps(layers, client_start,
62                                                    client_size);
63   display->total_stats().total_pixops_ += CalcPixOps(layers, 0, layers.size());
64
65   return *num_types ? HWC2::Error::HasChanges : HWC2::Error::None;
66 }
67
68 std::tuple<int, size_t> Backend::GetClientLayers(
69     DrmHwcTwo::HwcDisplay *display,
70     const std::vector<DrmHwcTwo::HwcLayer *> &layers) {
71   int client_start = -1;
72   size_t client_size = 0;
73
74   for (int z_order = 0; z_order < layers.size(); ++z_order) {
75     if (IsClientLayer(display, layers[z_order])) {
76       if (client_start < 0)
77         client_start = (int)z_order;
78       client_size = (z_order - client_start) + 1;
79     }
80   }
81
82   return GetExtraClientRange(display, layers, client_start, client_size);
83 }
84
85 bool Backend::IsClientLayer(DrmHwcTwo::HwcDisplay *display,
86                             DrmHwcTwo::HwcLayer *layer) {
87   return !HardwareSupportsLayerType(layer->sf_type()) ||
88          !BufferInfoGetter::GetInstance()->IsHandleUsable(layer->buffer()) ||
89          display->color_transform_hint() != HAL_COLOR_TRANSFORM_IDENTITY ||
90          (layer->RequireScalingOrPhasing() &&
91           display->resource_manager()->ForcedScalingWithGpu());
92 }
93
94 bool Backend::HardwareSupportsLayerType(HWC2::Composition comp_type) {
95   return comp_type == HWC2::Composition::Device ||
96          comp_type == HWC2::Composition::Cursor;
97 }
98
99 uint32_t Backend::CalcPixOps(const std::vector<DrmHwcTwo::HwcLayer *> &layers,
100                              size_t first_z, size_t size) {
101   uint32_t pixops = 0;
102   for (int z_order = 0; z_order < layers.size(); ++z_order) {
103     if (z_order >= first_z && z_order < first_z + size) {
104       hwc_rect_t df = layers[z_order]->display_frame();
105       pixops += (df.right - df.left) * (df.bottom - df.top);
106     }
107   }
108   return pixops;
109 }
110
111 void Backend::MarkValidated(std::vector<DrmHwcTwo::HwcLayer *> &layers,
112                             size_t client_first_z, size_t client_size) {
113   for (int z_order = 0; z_order < layers.size(); ++z_order) {
114     if (z_order >= client_first_z && z_order < client_first_z + client_size)
115       layers[z_order]->set_validated_type(HWC2::Composition::Client);
116     else
117       layers[z_order]->set_validated_type(HWC2::Composition::Device);
118   }
119 }
120
121 std::tuple<int, int> Backend::GetExtraClientRange(
122     DrmHwcTwo::HwcDisplay *display,
123     const std::vector<DrmHwcTwo::HwcLayer *> &layers, int client_start,
124     size_t client_size) {
125   size_t avail_planes = display->primary_planes().size() +
126                         display->overlay_planes().size();
127
128   /*
129    * If more layers then planes, save one plane
130    * for client composited layers
131    */
132   if (avail_planes < display->layers().size())
133     avail_planes--;
134
135   size_t extra_client = (layers.size() - client_size) - avail_planes;
136
137   if (extra_client > 0) {
138     int start = 0;
139     size_t steps = 0;
140     if (client_size != 0) {
141       size_t prepend = std::min((size_t)client_start, extra_client);
142       size_t append = std::min(layers.size() - (client_start + client_size),
143                                extra_client);
144       start = client_start - (int)prepend;
145       client_size += extra_client;
146       steps = 1 + std::min(std::min(append, prepend),
147                            int(layers.size()) - (start + client_size));
148     } else {
149       client_size = extra_client;
150       steps = 1 + layers.size() - extra_client;
151     }
152
153     uint32_t gpu_pixops = INT_MAX;
154     for (int i = 0; i < steps; i++) {
155       uint32_t po = CalcPixOps(layers, start + i, client_size);
156       if (po < gpu_pixops) {
157         gpu_pixops = po;
158         client_start = start + i;
159       }
160     }
161   }
162
163   return std::make_tuple(client_start, client_size);
164 }
165
166 // clang-format off
167 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp)
168 REGISTER_BACKEND("generic", Backend);
169 // clang-format on
170
171 }  // namespace android