xref: /aosp_15_r20/external/drm_hwcomposer/backend/Backend.cpp (revision 0a9764fe0a15e71ebbeb85e87e10990c23aab47f)
1*0a9764feSAndroid Build Coastguard Worker /*
2*0a9764feSAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
3*0a9764feSAndroid Build Coastguard Worker  *
4*0a9764feSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*0a9764feSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*0a9764feSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*0a9764feSAndroid Build Coastguard Worker  *
8*0a9764feSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*0a9764feSAndroid Build Coastguard Worker  *
10*0a9764feSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*0a9764feSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*0a9764feSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*0a9764feSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*0a9764feSAndroid Build Coastguard Worker  * limitations under the License.
15*0a9764feSAndroid Build Coastguard Worker  */
16*0a9764feSAndroid Build Coastguard Worker 
17*0a9764feSAndroid Build Coastguard Worker #include "Backend.h"
18*0a9764feSAndroid Build Coastguard Worker 
19*0a9764feSAndroid Build Coastguard Worker #include <climits>
20*0a9764feSAndroid Build Coastguard Worker 
21*0a9764feSAndroid Build Coastguard Worker #include "BackendManager.h"
22*0a9764feSAndroid Build Coastguard Worker #include "bufferinfo/BufferInfoGetter.h"
23*0a9764feSAndroid Build Coastguard Worker 
24*0a9764feSAndroid Build Coastguard Worker namespace android {
25*0a9764feSAndroid Build Coastguard Worker 
ValidateDisplay(HwcDisplay * display,uint32_t * num_types,uint32_t * num_requests)26*0a9764feSAndroid Build Coastguard Worker HWC2::Error Backend::ValidateDisplay(HwcDisplay *display, uint32_t *num_types,
27*0a9764feSAndroid Build Coastguard Worker                                      uint32_t *num_requests) {
28*0a9764feSAndroid Build Coastguard Worker   *num_types = 0;
29*0a9764feSAndroid Build Coastguard Worker   *num_requests = 0;
30*0a9764feSAndroid Build Coastguard Worker 
31*0a9764feSAndroid Build Coastguard Worker   auto layers = display->GetOrderLayersByZPos();
32*0a9764feSAndroid Build Coastguard Worker 
33*0a9764feSAndroid Build Coastguard Worker   int client_start = -1;
34*0a9764feSAndroid Build Coastguard Worker   size_t client_size = 0;
35*0a9764feSAndroid Build Coastguard Worker 
36*0a9764feSAndroid Build Coastguard Worker   auto flatcon = display->GetFlatCon();
37*0a9764feSAndroid Build Coastguard Worker   if (flatcon) {
38*0a9764feSAndroid Build Coastguard Worker     bool should_flatten = false;
39*0a9764feSAndroid Build Coastguard Worker     if (layers.size() <= 1)
40*0a9764feSAndroid Build Coastguard Worker       flatcon->Disable();
41*0a9764feSAndroid Build Coastguard Worker     else
42*0a9764feSAndroid Build Coastguard Worker       should_flatten = flatcon->NewFrame();
43*0a9764feSAndroid Build Coastguard Worker 
44*0a9764feSAndroid Build Coastguard Worker     if (should_flatten) {
45*0a9764feSAndroid Build Coastguard Worker       display->total_stats().frames_flattened_++;
46*0a9764feSAndroid Build Coastguard Worker       MarkValidated(layers, 0, layers.size());
47*0a9764feSAndroid Build Coastguard Worker       *num_types = layers.size();
48*0a9764feSAndroid Build Coastguard Worker       return HWC2::Error::HasChanges;
49*0a9764feSAndroid Build Coastguard Worker     }
50*0a9764feSAndroid Build Coastguard Worker   }
51*0a9764feSAndroid Build Coastguard Worker 
52*0a9764feSAndroid Build Coastguard Worker   std::tie(client_start, client_size) = GetClientLayers(display, layers);
53*0a9764feSAndroid Build Coastguard Worker 
54*0a9764feSAndroid Build Coastguard Worker   MarkValidated(layers, client_start, client_size);
55*0a9764feSAndroid Build Coastguard Worker 
56*0a9764feSAndroid Build Coastguard Worker   auto testing_needed = client_start != 0 || client_size != layers.size();
57*0a9764feSAndroid Build Coastguard Worker 
58*0a9764feSAndroid Build Coastguard Worker   AtomicCommitArgs a_args = {.test_only = true};
59*0a9764feSAndroid Build Coastguard Worker 
60*0a9764feSAndroid Build Coastguard Worker   if (testing_needed &&
61*0a9764feSAndroid Build Coastguard Worker       display->CreateComposition(a_args) != HWC2::Error::None) {
62*0a9764feSAndroid Build Coastguard Worker     ++display->total_stats().failed_kms_validate_;
63*0a9764feSAndroid Build Coastguard Worker     client_start = 0;
64*0a9764feSAndroid Build Coastguard Worker     client_size = layers.size();
65*0a9764feSAndroid Build Coastguard Worker     MarkValidated(layers, 0, client_size);
66*0a9764feSAndroid Build Coastguard Worker   }
67*0a9764feSAndroid Build Coastguard Worker 
68*0a9764feSAndroid Build Coastguard Worker   *num_types = client_size;
69*0a9764feSAndroid Build Coastguard Worker 
70*0a9764feSAndroid Build Coastguard Worker   display->total_stats().gpu_pixops_ += CalcPixOps(layers, client_start,
71*0a9764feSAndroid Build Coastguard Worker                                                    client_size);
72*0a9764feSAndroid Build Coastguard Worker   display->total_stats().total_pixops_ += CalcPixOps(layers, 0, layers.size());
73*0a9764feSAndroid Build Coastguard Worker 
74*0a9764feSAndroid Build Coastguard Worker   return *num_types != 0 ? HWC2::Error::HasChanges : HWC2::Error::None;
75*0a9764feSAndroid Build Coastguard Worker }
76*0a9764feSAndroid Build Coastguard Worker 
GetClientLayers(HwcDisplay * display,const std::vector<HwcLayer * > & layers)77*0a9764feSAndroid Build Coastguard Worker std::tuple<int, size_t> Backend::GetClientLayers(
78*0a9764feSAndroid Build Coastguard Worker     HwcDisplay *display, const std::vector<HwcLayer *> &layers) {
79*0a9764feSAndroid Build Coastguard Worker   int client_start = -1;
80*0a9764feSAndroid Build Coastguard Worker   size_t client_size = 0;
81*0a9764feSAndroid Build Coastguard Worker 
82*0a9764feSAndroid Build Coastguard Worker   for (size_t z_order = 0; z_order < layers.size(); ++z_order) {
83*0a9764feSAndroid Build Coastguard Worker     if (IsClientLayer(display, layers[z_order])) {
84*0a9764feSAndroid Build Coastguard Worker       if (client_start < 0)
85*0a9764feSAndroid Build Coastguard Worker         client_start = (int)z_order;
86*0a9764feSAndroid Build Coastguard Worker       client_size = (z_order - client_start) + 1;
87*0a9764feSAndroid Build Coastguard Worker     }
88*0a9764feSAndroid Build Coastguard Worker   }
89*0a9764feSAndroid Build Coastguard Worker 
90*0a9764feSAndroid Build Coastguard Worker   return GetExtraClientRange(display, layers, client_start, client_size);
91*0a9764feSAndroid Build Coastguard Worker }
92*0a9764feSAndroid Build Coastguard Worker 
IsClientLayer(HwcDisplay * display,HwcLayer * layer)93*0a9764feSAndroid Build Coastguard Worker bool Backend::IsClientLayer(HwcDisplay *display, HwcLayer *layer) {
94*0a9764feSAndroid Build Coastguard Worker   return !HardwareSupportsLayerType(layer->GetSfType()) ||
95*0a9764feSAndroid Build Coastguard Worker          !layer->IsLayerUsableAsDevice() || display->CtmByGpu() ||
96*0a9764feSAndroid Build Coastguard Worker          (layer->GetLayerData().pi.RequireScalingOrPhasing() &&
97*0a9764feSAndroid Build Coastguard Worker           display->GetHwc()->GetResMan().ForcedScalingWithGpu());
98*0a9764feSAndroid Build Coastguard Worker }
99*0a9764feSAndroid Build Coastguard Worker 
HardwareSupportsLayerType(HWC2::Composition comp_type)100*0a9764feSAndroid Build Coastguard Worker bool Backend::HardwareSupportsLayerType(HWC2::Composition comp_type) {
101*0a9764feSAndroid Build Coastguard Worker   return comp_type == HWC2::Composition::Device ||
102*0a9764feSAndroid Build Coastguard Worker          comp_type == HWC2::Composition::Cursor;
103*0a9764feSAndroid Build Coastguard Worker }
104*0a9764feSAndroid Build Coastguard Worker 
CalcPixOps(const std::vector<HwcLayer * > & layers,size_t first_z,size_t size)105*0a9764feSAndroid Build Coastguard Worker uint32_t Backend::CalcPixOps(const std::vector<HwcLayer *> &layers,
106*0a9764feSAndroid Build Coastguard Worker                              size_t first_z, size_t size) {
107*0a9764feSAndroid Build Coastguard Worker   uint32_t pixops = 0;
108*0a9764feSAndroid Build Coastguard Worker   for (size_t z_order = 0; z_order < layers.size(); ++z_order) {
109*0a9764feSAndroid Build Coastguard Worker     if (z_order >= first_z && z_order < first_z + size) {
110*0a9764feSAndroid Build Coastguard Worker       auto &df = layers[z_order]->GetLayerData().pi.display_frame;
111*0a9764feSAndroid Build Coastguard Worker       pixops += (df.right - df.left) * (df.bottom - df.top);
112*0a9764feSAndroid Build Coastguard Worker     }
113*0a9764feSAndroid Build Coastguard Worker   }
114*0a9764feSAndroid Build Coastguard Worker   return pixops;
115*0a9764feSAndroid Build Coastguard Worker }
116*0a9764feSAndroid Build Coastguard Worker 
MarkValidated(std::vector<HwcLayer * > & layers,size_t client_first_z,size_t client_size)117*0a9764feSAndroid Build Coastguard Worker void Backend::MarkValidated(std::vector<HwcLayer *> &layers,
118*0a9764feSAndroid Build Coastguard Worker                             size_t client_first_z, size_t client_size) {
119*0a9764feSAndroid Build Coastguard Worker   for (size_t z_order = 0; z_order < layers.size(); ++z_order) {
120*0a9764feSAndroid Build Coastguard Worker     if (z_order >= client_first_z && z_order < client_first_z + client_size)
121*0a9764feSAndroid Build Coastguard Worker       layers[z_order]->SetValidatedType(HWC2::Composition::Client);
122*0a9764feSAndroid Build Coastguard Worker     else
123*0a9764feSAndroid Build Coastguard Worker       layers[z_order]->SetValidatedType(HWC2::Composition::Device);
124*0a9764feSAndroid Build Coastguard Worker   }
125*0a9764feSAndroid Build Coastguard Worker }
126*0a9764feSAndroid Build Coastguard Worker 
GetExtraClientRange(HwcDisplay * display,const std::vector<HwcLayer * > & layers,int client_start,size_t client_size)127*0a9764feSAndroid Build Coastguard Worker std::tuple<int, int> Backend::GetExtraClientRange(
128*0a9764feSAndroid Build Coastguard Worker     HwcDisplay *display, const std::vector<HwcLayer *> &layers,
129*0a9764feSAndroid Build Coastguard Worker     int client_start, size_t client_size) {
130*0a9764feSAndroid Build Coastguard Worker   auto planes = display->GetPipe().GetUsablePlanes();
131*0a9764feSAndroid Build Coastguard Worker   size_t avail_planes = planes.size();
132*0a9764feSAndroid Build Coastguard Worker 
133*0a9764feSAndroid Build Coastguard Worker   /*
134*0a9764feSAndroid Build Coastguard Worker    * If more layers then planes, save one plane
135*0a9764feSAndroid Build Coastguard Worker    * for client composited layers
136*0a9764feSAndroid Build Coastguard Worker    */
137*0a9764feSAndroid Build Coastguard Worker   if (avail_planes < display->layers().size())
138*0a9764feSAndroid Build Coastguard Worker     avail_planes--;
139*0a9764feSAndroid Build Coastguard Worker 
140*0a9764feSAndroid Build Coastguard Worker   const int extra_client = int(layers.size() - client_size) - int(avail_planes);
141*0a9764feSAndroid Build Coastguard Worker 
142*0a9764feSAndroid Build Coastguard Worker   if (extra_client > 0) {
143*0a9764feSAndroid Build Coastguard Worker     int start = 0;
144*0a9764feSAndroid Build Coastguard Worker     size_t steps = 0;
145*0a9764feSAndroid Build Coastguard Worker     if (client_size != 0) {
146*0a9764feSAndroid Build Coastguard Worker       const int prepend = std::min(client_start, extra_client);
147*0a9764feSAndroid Build Coastguard Worker       const int append = std::min(int(layers.size()) -
148*0a9764feSAndroid Build Coastguard Worker                                       int(client_start + client_size),
149*0a9764feSAndroid Build Coastguard Worker                                   extra_client);
150*0a9764feSAndroid Build Coastguard Worker       start = client_start - (int)prepend;
151*0a9764feSAndroid Build Coastguard Worker       client_size += extra_client;
152*0a9764feSAndroid Build Coastguard Worker       steps = 1 + std::min(std::min(append, prepend),
153*0a9764feSAndroid Build Coastguard Worker                            int(layers.size()) - int(start + client_size));
154*0a9764feSAndroid Build Coastguard Worker     } else {
155*0a9764feSAndroid Build Coastguard Worker       client_size = extra_client;
156*0a9764feSAndroid Build Coastguard Worker       steps = 1 + layers.size() - extra_client;
157*0a9764feSAndroid Build Coastguard Worker     }
158*0a9764feSAndroid Build Coastguard Worker 
159*0a9764feSAndroid Build Coastguard Worker     uint32_t gpu_pixops = UINT32_MAX;
160*0a9764feSAndroid Build Coastguard Worker     for (size_t i = 0; i < steps; i++) {
161*0a9764feSAndroid Build Coastguard Worker       const uint32_t po = CalcPixOps(layers, start + i, client_size);
162*0a9764feSAndroid Build Coastguard Worker       if (po < gpu_pixops) {
163*0a9764feSAndroid Build Coastguard Worker         gpu_pixops = po;
164*0a9764feSAndroid Build Coastguard Worker         client_start = start + int(i);
165*0a9764feSAndroid Build Coastguard Worker       }
166*0a9764feSAndroid Build Coastguard Worker     }
167*0a9764feSAndroid Build Coastguard Worker   }
168*0a9764feSAndroid Build Coastguard Worker 
169*0a9764feSAndroid Build Coastguard Worker   return std::make_tuple(client_start, client_size);
170*0a9764feSAndroid Build Coastguard Worker }
171*0a9764feSAndroid Build Coastguard Worker 
172*0a9764feSAndroid Build Coastguard Worker // clang-format off
173*0a9764feSAndroid Build Coastguard Worker // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp)
174*0a9764feSAndroid Build Coastguard Worker REGISTER_BACKEND("generic", Backend);
175*0a9764feSAndroid Build Coastguard Worker // clang-format on
176*0a9764feSAndroid Build Coastguard Worker 
177*0a9764feSAndroid Build Coastguard Worker }  // namespace android
178