xref: /aosp_15_r20/external/drm_hwcomposer/hwc2_device/HwcDisplay.cpp (revision 0a9764fe0a15e71ebbeb85e87e10990c23aab47f)
1*0a9764feSAndroid Build Coastguard Worker /*
2*0a9764feSAndroid Build Coastguard Worker  * Copyright (C) 2022 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 #define LOG_TAG "drmhwc"
18*0a9764feSAndroid Build Coastguard Worker #define ATRACE_TAG ATRACE_TAG_GRAPHICS
19*0a9764feSAndroid Build Coastguard Worker 
20*0a9764feSAndroid Build Coastguard Worker #include "HwcDisplay.h"
21*0a9764feSAndroid Build Coastguard Worker 
22*0a9764feSAndroid Build Coastguard Worker #include <cinttypes>
23*0a9764feSAndroid Build Coastguard Worker 
24*0a9764feSAndroid Build Coastguard Worker #include <hardware/gralloc.h>
25*0a9764feSAndroid Build Coastguard Worker #include <ui/GraphicBufferAllocator.h>
26*0a9764feSAndroid Build Coastguard Worker #include <ui/GraphicBufferMapper.h>
27*0a9764feSAndroid Build Coastguard Worker #include <ui/PixelFormat.h>
28*0a9764feSAndroid Build Coastguard Worker 
29*0a9764feSAndroid Build Coastguard Worker #include "backend/Backend.h"
30*0a9764feSAndroid Build Coastguard Worker #include "backend/BackendManager.h"
31*0a9764feSAndroid Build Coastguard Worker #include "bufferinfo/BufferInfoGetter.h"
32*0a9764feSAndroid Build Coastguard Worker #include "compositor/DisplayInfo.h"
33*0a9764feSAndroid Build Coastguard Worker #include "drm/DrmConnector.h"
34*0a9764feSAndroid Build Coastguard Worker #include "drm/DrmDisplayPipeline.h"
35*0a9764feSAndroid Build Coastguard Worker #include "drm/DrmHwc.h"
36*0a9764feSAndroid Build Coastguard Worker #include "utils/log.h"
37*0a9764feSAndroid Build Coastguard Worker #include "utils/properties.h"
38*0a9764feSAndroid Build Coastguard Worker 
39*0a9764feSAndroid Build Coastguard Worker using ::android::DrmDisplayPipeline;
40*0a9764feSAndroid Build Coastguard Worker 
41*0a9764feSAndroid Build Coastguard Worker namespace android {
42*0a9764feSAndroid Build Coastguard Worker 
43*0a9764feSAndroid Build Coastguard Worker namespace {
44*0a9764feSAndroid Build Coastguard Worker // Allocate a black buffer that can be used for an initial modeset when there.
45*0a9764feSAndroid Build Coastguard Worker // is no appropriate client buffer available to be used.
46*0a9764feSAndroid Build Coastguard Worker // Caller must free the returned buffer with GraphicBufferAllocator::free.
GetModesetBuffer(uint32_t width,uint32_t height)47*0a9764feSAndroid Build Coastguard Worker auto GetModesetBuffer(uint32_t width, uint32_t height) -> buffer_handle_t {
48*0a9764feSAndroid Build Coastguard Worker   constexpr PixelFormat format = PIXEL_FORMAT_RGBA_8888;
49*0a9764feSAndroid Build Coastguard Worker   constexpr uint64_t usage = GRALLOC_USAGE_SW_READ_OFTEN |
50*0a9764feSAndroid Build Coastguard Worker                              GRALLOC_USAGE_SW_WRITE_OFTEN |
51*0a9764feSAndroid Build Coastguard Worker                              GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_FB;
52*0a9764feSAndroid Build Coastguard Worker 
53*0a9764feSAndroid Build Coastguard Worker   constexpr uint32_t layer_count = 1;
54*0a9764feSAndroid Build Coastguard Worker   const std::string name = "drm-hwcomposer";
55*0a9764feSAndroid Build Coastguard Worker 
56*0a9764feSAndroid Build Coastguard Worker   buffer_handle_t handle = nullptr;
57*0a9764feSAndroid Build Coastguard Worker   uint32_t stride = 0;
58*0a9764feSAndroid Build Coastguard Worker   status_t status = GraphicBufferAllocator::get().allocate(width, height,
59*0a9764feSAndroid Build Coastguard Worker                                                            format, layer_count,
60*0a9764feSAndroid Build Coastguard Worker                                                            usage, &handle,
61*0a9764feSAndroid Build Coastguard Worker                                                            &stride, name);
62*0a9764feSAndroid Build Coastguard Worker   if (status != OK) {
63*0a9764feSAndroid Build Coastguard Worker     ALOGE("Failed to allocate modeset buffer.");
64*0a9764feSAndroid Build Coastguard Worker     return nullptr;
65*0a9764feSAndroid Build Coastguard Worker   }
66*0a9764feSAndroid Build Coastguard Worker 
67*0a9764feSAndroid Build Coastguard Worker   void *data = nullptr;
68*0a9764feSAndroid Build Coastguard Worker   Rect bounds = {0, 0, static_cast<int32_t>(width),
69*0a9764feSAndroid Build Coastguard Worker                  static_cast<int32_t>(height)};
70*0a9764feSAndroid Build Coastguard Worker   status = GraphicBufferMapper::get().lock(handle, usage, bounds, &data);
71*0a9764feSAndroid Build Coastguard Worker   if (status != OK) {
72*0a9764feSAndroid Build Coastguard Worker     ALOGE("Failed to map modeset buffer.");
73*0a9764feSAndroid Build Coastguard Worker     GraphicBufferAllocator::get().free(handle);
74*0a9764feSAndroid Build Coastguard Worker     return nullptr;
75*0a9764feSAndroid Build Coastguard Worker   }
76*0a9764feSAndroid Build Coastguard Worker 
77*0a9764feSAndroid Build Coastguard Worker   // Cast one of the multiplicands to ensure that the multiplication happens
78*0a9764feSAndroid Build Coastguard Worker   // in a wider type (size_t).
79*0a9764feSAndroid Build Coastguard Worker   const size_t buffer_size = static_cast<size_t>(height) * stride *
80*0a9764feSAndroid Build Coastguard Worker                              bytesPerPixel(format);
81*0a9764feSAndroid Build Coastguard Worker   memset(data, 0, buffer_size);
82*0a9764feSAndroid Build Coastguard Worker   status = GraphicBufferMapper::get().unlock(handle);
83*0a9764feSAndroid Build Coastguard Worker   ALOGW_IF(status != OK, "Failed to unmap buffer.");
84*0a9764feSAndroid Build Coastguard Worker   return handle;
85*0a9764feSAndroid Build Coastguard Worker }
86*0a9764feSAndroid Build Coastguard Worker 
GetModesetLayerProperties(buffer_handle_t buffer,uint32_t width,uint32_t height)87*0a9764feSAndroid Build Coastguard Worker auto GetModesetLayerProperties(buffer_handle_t buffer, uint32_t width,
88*0a9764feSAndroid Build Coastguard Worker                                uint32_t height) -> HwcLayer::LayerProperties {
89*0a9764feSAndroid Build Coastguard Worker   HwcLayer::LayerProperties properties;
90*0a9764feSAndroid Build Coastguard Worker   properties.buffer = {.buffer_handle = buffer, .acquire_fence = {}};
91*0a9764feSAndroid Build Coastguard Worker   properties.display_frame = {
92*0a9764feSAndroid Build Coastguard Worker       .left = 0,
93*0a9764feSAndroid Build Coastguard Worker       .top = 0,
94*0a9764feSAndroid Build Coastguard Worker       .right = int(width),
95*0a9764feSAndroid Build Coastguard Worker       .bottom = int(height),
96*0a9764feSAndroid Build Coastguard Worker   };
97*0a9764feSAndroid Build Coastguard Worker   properties.source_crop = (hwc_frect_t){
98*0a9764feSAndroid Build Coastguard Worker       .left = 0.0F,
99*0a9764feSAndroid Build Coastguard Worker       .top = 0.0F,
100*0a9764feSAndroid Build Coastguard Worker       .right = static_cast<float>(width),
101*0a9764feSAndroid Build Coastguard Worker       .bottom = static_cast<float>(height),
102*0a9764feSAndroid Build Coastguard Worker   };
103*0a9764feSAndroid Build Coastguard Worker   properties.blend_mode = BufferBlendMode::kNone;
104*0a9764feSAndroid Build Coastguard Worker   return properties;
105*0a9764feSAndroid Build Coastguard Worker }
106*0a9764feSAndroid Build Coastguard Worker }  // namespace
107*0a9764feSAndroid Build Coastguard Worker 
DumpDelta(HwcDisplay::Stats delta)108*0a9764feSAndroid Build Coastguard Worker std::string HwcDisplay::DumpDelta(HwcDisplay::Stats delta) {
109*0a9764feSAndroid Build Coastguard Worker   if (delta.total_pixops_ == 0)
110*0a9764feSAndroid Build Coastguard Worker     return "No stats yet";
111*0a9764feSAndroid Build Coastguard Worker   auto ratio = 1.0 - double(delta.gpu_pixops_) / double(delta.total_pixops_);
112*0a9764feSAndroid Build Coastguard Worker 
113*0a9764feSAndroid Build Coastguard Worker   std::stringstream ss;
114*0a9764feSAndroid Build Coastguard Worker   ss << " Total frames count: " << delta.total_frames_ << "\n"
115*0a9764feSAndroid Build Coastguard Worker      << " Failed to test commit frames: " << delta.failed_kms_validate_ << "\n"
116*0a9764feSAndroid Build Coastguard Worker      << " Failed to commit frames: " << delta.failed_kms_present_ << "\n"
117*0a9764feSAndroid Build Coastguard Worker      << ((delta.failed_kms_present_ > 0)
118*0a9764feSAndroid Build Coastguard Worker              ? " !!! Internal failure, FIX it please\n"
119*0a9764feSAndroid Build Coastguard Worker              : "")
120*0a9764feSAndroid Build Coastguard Worker      << " Flattened frames: " << delta.frames_flattened_ << "\n"
121*0a9764feSAndroid Build Coastguard Worker      << " Pixel operations (free units)"
122*0a9764feSAndroid Build Coastguard Worker      << " : [TOTAL: " << delta.total_pixops_ << " / GPU: " << delta.gpu_pixops_
123*0a9764feSAndroid Build Coastguard Worker      << "]\n"
124*0a9764feSAndroid Build Coastguard Worker      << " Composition efficiency: " << ratio;
125*0a9764feSAndroid Build Coastguard Worker 
126*0a9764feSAndroid Build Coastguard Worker   return ss.str();
127*0a9764feSAndroid Build Coastguard Worker }
128*0a9764feSAndroid Build Coastguard Worker 
Dump()129*0a9764feSAndroid Build Coastguard Worker std::string HwcDisplay::Dump() {
130*0a9764feSAndroid Build Coastguard Worker   auto connector_name = IsInHeadlessMode()
131*0a9764feSAndroid Build Coastguard Worker                             ? std::string("NULL-DISPLAY")
132*0a9764feSAndroid Build Coastguard Worker                             : GetPipe().connector->Get()->GetName();
133*0a9764feSAndroid Build Coastguard Worker 
134*0a9764feSAndroid Build Coastguard Worker   std::stringstream ss;
135*0a9764feSAndroid Build Coastguard Worker   ss << "- Display on: " << connector_name << "\n"
136*0a9764feSAndroid Build Coastguard Worker      << "Statistics since system boot:\n"
137*0a9764feSAndroid Build Coastguard Worker      << DumpDelta(total_stats_) << "\n\n"
138*0a9764feSAndroid Build Coastguard Worker      << "Statistics since last dumpsys request:\n"
139*0a9764feSAndroid Build Coastguard Worker      << DumpDelta(total_stats_.minus(prev_stats_)) << "\n\n";
140*0a9764feSAndroid Build Coastguard Worker 
141*0a9764feSAndroid Build Coastguard Worker   memcpy(&prev_stats_, &total_stats_, sizeof(Stats));
142*0a9764feSAndroid Build Coastguard Worker   return ss.str();
143*0a9764feSAndroid Build Coastguard Worker }
144*0a9764feSAndroid Build Coastguard Worker 
HwcDisplay(hwc2_display_t handle,HWC2::DisplayType type,DrmHwc * hwc)145*0a9764feSAndroid Build Coastguard Worker HwcDisplay::HwcDisplay(hwc2_display_t handle, HWC2::DisplayType type,
146*0a9764feSAndroid Build Coastguard Worker                        DrmHwc *hwc)
147*0a9764feSAndroid Build Coastguard Worker     : hwc_(hwc), handle_(handle), type_(type), client_layer_(this) {
148*0a9764feSAndroid Build Coastguard Worker   if (type_ == HWC2::DisplayType::Virtual) {
149*0a9764feSAndroid Build Coastguard Worker     writeback_layer_ = std::make_unique<HwcLayer>(this);
150*0a9764feSAndroid Build Coastguard Worker   }
151*0a9764feSAndroid Build Coastguard Worker }
152*0a9764feSAndroid Build Coastguard Worker 
SetColorMatrixToIdentity()153*0a9764feSAndroid Build Coastguard Worker void HwcDisplay::SetColorMatrixToIdentity() {
154*0a9764feSAndroid Build Coastguard Worker   color_matrix_ = std::make_shared<drm_color_ctm>();
155*0a9764feSAndroid Build Coastguard Worker   for (int i = 0; i < kCtmCols; i++) {
156*0a9764feSAndroid Build Coastguard Worker     for (int j = 0; j < kCtmRows; j++) {
157*0a9764feSAndroid Build Coastguard Worker       constexpr uint64_t kOne = (1ULL << 32); /* 1.0 in s31.32 format */
158*0a9764feSAndroid Build Coastguard Worker       color_matrix_->matrix[i * kCtmRows + j] = (i == j) ? kOne : 0;
159*0a9764feSAndroid Build Coastguard Worker     }
160*0a9764feSAndroid Build Coastguard Worker   }
161*0a9764feSAndroid Build Coastguard Worker 
162*0a9764feSAndroid Build Coastguard Worker   color_transform_hint_ = HAL_COLOR_TRANSFORM_IDENTITY;
163*0a9764feSAndroid Build Coastguard Worker }
164*0a9764feSAndroid Build Coastguard Worker 
~HwcDisplay()165*0a9764feSAndroid Build Coastguard Worker HwcDisplay::~HwcDisplay() {
166*0a9764feSAndroid Build Coastguard Worker   Deinit();
167*0a9764feSAndroid Build Coastguard Worker };
168*0a9764feSAndroid Build Coastguard Worker 
GetConfig(hwc2_config_t config_id) const169*0a9764feSAndroid Build Coastguard Worker auto HwcDisplay::GetConfig(hwc2_config_t config_id) const
170*0a9764feSAndroid Build Coastguard Worker     -> const HwcDisplayConfig * {
171*0a9764feSAndroid Build Coastguard Worker   auto config_iter = configs_.hwc_configs.find(config_id);
172*0a9764feSAndroid Build Coastguard Worker   if (config_iter == configs_.hwc_configs.end()) {
173*0a9764feSAndroid Build Coastguard Worker     return nullptr;
174*0a9764feSAndroid Build Coastguard Worker   }
175*0a9764feSAndroid Build Coastguard Worker   return &config_iter->second;
176*0a9764feSAndroid Build Coastguard Worker }
177*0a9764feSAndroid Build Coastguard Worker 
GetCurrentConfig() const178*0a9764feSAndroid Build Coastguard Worker auto HwcDisplay::GetCurrentConfig() const -> const HwcDisplayConfig * {
179*0a9764feSAndroid Build Coastguard Worker   return GetConfig(configs_.active_config_id);
180*0a9764feSAndroid Build Coastguard Worker }
181*0a9764feSAndroid Build Coastguard Worker 
GetLastRequestedConfig() const182*0a9764feSAndroid Build Coastguard Worker auto HwcDisplay::GetLastRequestedConfig() const -> const HwcDisplayConfig * {
183*0a9764feSAndroid Build Coastguard Worker   return GetConfig(staged_mode_config_id_.value_or(configs_.active_config_id));
184*0a9764feSAndroid Build Coastguard Worker }
185*0a9764feSAndroid Build Coastguard Worker 
SetConfig(hwc2_config_t config)186*0a9764feSAndroid Build Coastguard Worker HwcDisplay::ConfigError HwcDisplay::SetConfig(hwc2_config_t config) {
187*0a9764feSAndroid Build Coastguard Worker   const HwcDisplayConfig *new_config = GetConfig(config);
188*0a9764feSAndroid Build Coastguard Worker   if (new_config == nullptr) {
189*0a9764feSAndroid Build Coastguard Worker     ALOGE("Could not find active mode for %u", config);
190*0a9764feSAndroid Build Coastguard Worker     return ConfigError::kBadConfig;
191*0a9764feSAndroid Build Coastguard Worker   }
192*0a9764feSAndroid Build Coastguard Worker 
193*0a9764feSAndroid Build Coastguard Worker   const HwcDisplayConfig *current_config = GetCurrentConfig();
194*0a9764feSAndroid Build Coastguard Worker 
195*0a9764feSAndroid Build Coastguard Worker   const uint32_t width = new_config->mode.GetRawMode().hdisplay;
196*0a9764feSAndroid Build Coastguard Worker   const uint32_t height = new_config->mode.GetRawMode().vdisplay;
197*0a9764feSAndroid Build Coastguard Worker 
198*0a9764feSAndroid Build Coastguard Worker   std::optional<LayerData> modeset_layer_data;
199*0a9764feSAndroid Build Coastguard Worker   // If a client layer has already been provided, and its size matches the
200*0a9764feSAndroid Build Coastguard Worker   // new config, use it for the modeset.
201*0a9764feSAndroid Build Coastguard Worker   if (client_layer_.IsLayerUsableAsDevice() && current_config &&
202*0a9764feSAndroid Build Coastguard Worker       current_config->mode.GetRawMode().hdisplay == width &&
203*0a9764feSAndroid Build Coastguard Worker       current_config->mode.GetRawMode().vdisplay == height) {
204*0a9764feSAndroid Build Coastguard Worker     ALOGV("Use existing client_layer for blocking config.");
205*0a9764feSAndroid Build Coastguard Worker     modeset_layer_data = client_layer_.GetLayerData();
206*0a9764feSAndroid Build Coastguard Worker   } else {
207*0a9764feSAndroid Build Coastguard Worker     ALOGV("Allocate modeset buffer.");
208*0a9764feSAndroid Build Coastguard Worker     buffer_handle_t modeset_buffer = GetModesetBuffer(width, height);
209*0a9764feSAndroid Build Coastguard Worker     if (modeset_buffer != nullptr) {
210*0a9764feSAndroid Build Coastguard Worker       auto modeset_layer = std::make_unique<HwcLayer>(this);
211*0a9764feSAndroid Build Coastguard Worker       modeset_layer->SetLayerProperties(
212*0a9764feSAndroid Build Coastguard Worker           GetModesetLayerProperties(modeset_buffer, width, height));
213*0a9764feSAndroid Build Coastguard Worker       modeset_layer->PopulateLayerData();
214*0a9764feSAndroid Build Coastguard Worker       modeset_layer_data = modeset_layer->GetLayerData();
215*0a9764feSAndroid Build Coastguard Worker       GraphicBufferAllocator::get().free(modeset_buffer);
216*0a9764feSAndroid Build Coastguard Worker     }
217*0a9764feSAndroid Build Coastguard Worker   }
218*0a9764feSAndroid Build Coastguard Worker 
219*0a9764feSAndroid Build Coastguard Worker   ALOGV("Create modeset commit.");
220*0a9764feSAndroid Build Coastguard Worker   // Create atomic commit args for a blocking modeset. There's no need to do a
221*0a9764feSAndroid Build Coastguard Worker   // separate test commit, since the commit does a test anyways.
222*0a9764feSAndroid Build Coastguard Worker   AtomicCommitArgs commit_args = CreateModesetCommit(new_config,
223*0a9764feSAndroid Build Coastguard Worker                                                      modeset_layer_data);
224*0a9764feSAndroid Build Coastguard Worker   commit_args.blocking = true;
225*0a9764feSAndroid Build Coastguard Worker   int ret = GetPipe().atomic_state_manager->ExecuteAtomicCommit(commit_args);
226*0a9764feSAndroid Build Coastguard Worker 
227*0a9764feSAndroid Build Coastguard Worker   if (ret) {
228*0a9764feSAndroid Build Coastguard Worker     ALOGE("Blocking config failed: %d", ret);
229*0a9764feSAndroid Build Coastguard Worker     return HwcDisplay::ConfigError::kBadConfig;
230*0a9764feSAndroid Build Coastguard Worker   }
231*0a9764feSAndroid Build Coastguard Worker 
232*0a9764feSAndroid Build Coastguard Worker   ALOGV("Blocking config succeeded.");
233*0a9764feSAndroid Build Coastguard Worker   configs_.active_config_id = config;
234*0a9764feSAndroid Build Coastguard Worker   staged_mode_config_id_.reset();
235*0a9764feSAndroid Build Coastguard Worker   return ConfigError::kNone;
236*0a9764feSAndroid Build Coastguard Worker }
237*0a9764feSAndroid Build Coastguard Worker 
QueueConfig(hwc2_config_t config,int64_t desired_time,bool seamless,QueuedConfigTiming * out_timing)238*0a9764feSAndroid Build Coastguard Worker auto HwcDisplay::QueueConfig(hwc2_config_t config, int64_t desired_time,
239*0a9764feSAndroid Build Coastguard Worker                              bool seamless, QueuedConfigTiming *out_timing)
240*0a9764feSAndroid Build Coastguard Worker     -> ConfigError {
241*0a9764feSAndroid Build Coastguard Worker   if (configs_.hwc_configs.count(config) == 0) {
242*0a9764feSAndroid Build Coastguard Worker     ALOGE("Could not find active mode for %u", config);
243*0a9764feSAndroid Build Coastguard Worker     return ConfigError::kBadConfig;
244*0a9764feSAndroid Build Coastguard Worker   }
245*0a9764feSAndroid Build Coastguard Worker 
246*0a9764feSAndroid Build Coastguard Worker   // TODO: Add support for seamless configuration changes.
247*0a9764feSAndroid Build Coastguard Worker   if (seamless) {
248*0a9764feSAndroid Build Coastguard Worker     return ConfigError::kSeamlessNotAllowed;
249*0a9764feSAndroid Build Coastguard Worker   }
250*0a9764feSAndroid Build Coastguard Worker 
251*0a9764feSAndroid Build Coastguard Worker   // Request a refresh from the client one vsync period before the desired
252*0a9764feSAndroid Build Coastguard Worker   // time, or simply at the desired time if there is no active configuration.
253*0a9764feSAndroid Build Coastguard Worker   const HwcDisplayConfig *current_config = GetCurrentConfig();
254*0a9764feSAndroid Build Coastguard Worker   out_timing->refresh_time_ns = desired_time -
255*0a9764feSAndroid Build Coastguard Worker                                 (current_config
256*0a9764feSAndroid Build Coastguard Worker                                      ? current_config->mode.GetVSyncPeriodNs()
257*0a9764feSAndroid Build Coastguard Worker                                      : 0);
258*0a9764feSAndroid Build Coastguard Worker   out_timing->new_vsync_time_ns = desired_time;
259*0a9764feSAndroid Build Coastguard Worker 
260*0a9764feSAndroid Build Coastguard Worker   // Queue the config change timing to be consistent with the requested
261*0a9764feSAndroid Build Coastguard Worker   // refresh time.
262*0a9764feSAndroid Build Coastguard Worker   staged_mode_change_time_ = out_timing->refresh_time_ns;
263*0a9764feSAndroid Build Coastguard Worker   staged_mode_config_id_ = config;
264*0a9764feSAndroid Build Coastguard Worker 
265*0a9764feSAndroid Build Coastguard Worker   // Enable vsync events until the mode has been applied.
266*0a9764feSAndroid Build Coastguard Worker   last_vsync_ts_ = 0;
267*0a9764feSAndroid Build Coastguard Worker   vsync_tracking_en_ = true;
268*0a9764feSAndroid Build Coastguard Worker   vsync_worker_->VSyncControl(true);
269*0a9764feSAndroid Build Coastguard Worker 
270*0a9764feSAndroid Build Coastguard Worker   return ConfigError::kNone;
271*0a9764feSAndroid Build Coastguard Worker }
272*0a9764feSAndroid Build Coastguard Worker 
SetPipeline(std::shared_ptr<DrmDisplayPipeline> pipeline)273*0a9764feSAndroid Build Coastguard Worker void HwcDisplay::SetPipeline(std::shared_ptr<DrmDisplayPipeline> pipeline) {
274*0a9764feSAndroid Build Coastguard Worker   Deinit();
275*0a9764feSAndroid Build Coastguard Worker 
276*0a9764feSAndroid Build Coastguard Worker   pipeline_ = std::move(pipeline);
277*0a9764feSAndroid Build Coastguard Worker 
278*0a9764feSAndroid Build Coastguard Worker   if (pipeline_ != nullptr || handle_ == kPrimaryDisplay) {
279*0a9764feSAndroid Build Coastguard Worker     Init();
280*0a9764feSAndroid Build Coastguard Worker     hwc_->ScheduleHotplugEvent(handle_, DrmHwc::kConnected);
281*0a9764feSAndroid Build Coastguard Worker   } else {
282*0a9764feSAndroid Build Coastguard Worker     hwc_->ScheduleHotplugEvent(handle_, DrmHwc::kDisconnected);
283*0a9764feSAndroid Build Coastguard Worker   }
284*0a9764feSAndroid Build Coastguard Worker }
285*0a9764feSAndroid Build Coastguard Worker 
Deinit()286*0a9764feSAndroid Build Coastguard Worker void HwcDisplay::Deinit() {
287*0a9764feSAndroid Build Coastguard Worker   if (pipeline_ != nullptr) {
288*0a9764feSAndroid Build Coastguard Worker     AtomicCommitArgs a_args{};
289*0a9764feSAndroid Build Coastguard Worker     a_args.composition = std::make_shared<DrmKmsPlan>();
290*0a9764feSAndroid Build Coastguard Worker     GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args);
291*0a9764feSAndroid Build Coastguard Worker     a_args.composition = {};
292*0a9764feSAndroid Build Coastguard Worker     a_args.active = false;
293*0a9764feSAndroid Build Coastguard Worker     GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args);
294*0a9764feSAndroid Build Coastguard Worker 
295*0a9764feSAndroid Build Coastguard Worker     current_plan_.reset();
296*0a9764feSAndroid Build Coastguard Worker     backend_.reset();
297*0a9764feSAndroid Build Coastguard Worker     if (flatcon_) {
298*0a9764feSAndroid Build Coastguard Worker       flatcon_->StopThread();
299*0a9764feSAndroid Build Coastguard Worker       flatcon_.reset();
300*0a9764feSAndroid Build Coastguard Worker     }
301*0a9764feSAndroid Build Coastguard Worker   }
302*0a9764feSAndroid Build Coastguard Worker 
303*0a9764feSAndroid Build Coastguard Worker   if (vsync_worker_) {
304*0a9764feSAndroid Build Coastguard Worker     // TODO: There should be a mechanism to wait for this worker to complete,
305*0a9764feSAndroid Build Coastguard Worker     // otherwise there is a race condition while destructing the HwcDisplay.
306*0a9764feSAndroid Build Coastguard Worker     vsync_worker_->StopThread();
307*0a9764feSAndroid Build Coastguard Worker     vsync_worker_ = {};
308*0a9764feSAndroid Build Coastguard Worker   }
309*0a9764feSAndroid Build Coastguard Worker 
310*0a9764feSAndroid Build Coastguard Worker   SetClientTarget(nullptr, -1, 0, {});
311*0a9764feSAndroid Build Coastguard Worker }
312*0a9764feSAndroid Build Coastguard Worker 
Init()313*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::Init() {
314*0a9764feSAndroid Build Coastguard Worker   ChosePreferredConfig();
315*0a9764feSAndroid Build Coastguard Worker 
316*0a9764feSAndroid Build Coastguard Worker   auto vsw_callbacks = (VSyncWorkerCallbacks){
317*0a9764feSAndroid Build Coastguard Worker       .out_event =
318*0a9764feSAndroid Build Coastguard Worker           [this](int64_t timestamp) {
319*0a9764feSAndroid Build Coastguard Worker             const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
320*0a9764feSAndroid Build Coastguard Worker             if (vsync_event_en_) {
321*0a9764feSAndroid Build Coastguard Worker               uint32_t period_ns{};
322*0a9764feSAndroid Build Coastguard Worker               GetDisplayVsyncPeriod(&period_ns);
323*0a9764feSAndroid Build Coastguard Worker               hwc_->SendVsyncEventToClient(handle_, timestamp, period_ns);
324*0a9764feSAndroid Build Coastguard Worker             }
325*0a9764feSAndroid Build Coastguard Worker             if (vsync_tracking_en_) {
326*0a9764feSAndroid Build Coastguard Worker               last_vsync_ts_ = timestamp;
327*0a9764feSAndroid Build Coastguard Worker             }
328*0a9764feSAndroid Build Coastguard Worker             if (!vsync_event_en_ && !vsync_tracking_en_) {
329*0a9764feSAndroid Build Coastguard Worker               vsync_worker_->VSyncControl(false);
330*0a9764feSAndroid Build Coastguard Worker             }
331*0a9764feSAndroid Build Coastguard Worker           },
332*0a9764feSAndroid Build Coastguard Worker       .get_vperiod_ns = [this]() -> uint32_t {
333*0a9764feSAndroid Build Coastguard Worker         uint32_t outVsyncPeriod = 0;
334*0a9764feSAndroid Build Coastguard Worker         GetDisplayVsyncPeriod(&outVsyncPeriod);
335*0a9764feSAndroid Build Coastguard Worker         return outVsyncPeriod;
336*0a9764feSAndroid Build Coastguard Worker       },
337*0a9764feSAndroid Build Coastguard Worker   };
338*0a9764feSAndroid Build Coastguard Worker 
339*0a9764feSAndroid Build Coastguard Worker   if (type_ != HWC2::DisplayType::Virtual) {
340*0a9764feSAndroid Build Coastguard Worker     vsync_worker_ = VSyncWorker::CreateInstance(pipeline_, vsw_callbacks);
341*0a9764feSAndroid Build Coastguard Worker     if (!vsync_worker_) {
342*0a9764feSAndroid Build Coastguard Worker       ALOGE("Failed to create event worker for d=%d\n", int(handle_));
343*0a9764feSAndroid Build Coastguard Worker       return HWC2::Error::BadDisplay;
344*0a9764feSAndroid Build Coastguard Worker     }
345*0a9764feSAndroid Build Coastguard Worker   }
346*0a9764feSAndroid Build Coastguard Worker 
347*0a9764feSAndroid Build Coastguard Worker   if (!IsInHeadlessMode()) {
348*0a9764feSAndroid Build Coastguard Worker     auto ret = BackendManager::GetInstance().SetBackendForDisplay(this);
349*0a9764feSAndroid Build Coastguard Worker     if (ret) {
350*0a9764feSAndroid Build Coastguard Worker       ALOGE("Failed to set backend for d=%d %d\n", int(handle_), ret);
351*0a9764feSAndroid Build Coastguard Worker       return HWC2::Error::BadDisplay;
352*0a9764feSAndroid Build Coastguard Worker     }
353*0a9764feSAndroid Build Coastguard Worker     auto flatcbk = (struct FlatConCallbacks){
354*0a9764feSAndroid Build Coastguard Worker         .trigger = [this]() { hwc_->SendRefreshEventToClient(handle_); }};
355*0a9764feSAndroid Build Coastguard Worker     flatcon_ = FlatteningController::CreateInstance(flatcbk);
356*0a9764feSAndroid Build Coastguard Worker   }
357*0a9764feSAndroid Build Coastguard Worker 
358*0a9764feSAndroid Build Coastguard Worker   client_layer_.SetLayerBlendMode(HWC2_BLEND_MODE_PREMULTIPLIED);
359*0a9764feSAndroid Build Coastguard Worker 
360*0a9764feSAndroid Build Coastguard Worker   SetColorMatrixToIdentity();
361*0a9764feSAndroid Build Coastguard Worker 
362*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
363*0a9764feSAndroid Build Coastguard Worker }
364*0a9764feSAndroid Build Coastguard Worker 
getDisplayPhysicalOrientation()365*0a9764feSAndroid Build Coastguard Worker std::optional<PanelOrientation> HwcDisplay::getDisplayPhysicalOrientation() {
366*0a9764feSAndroid Build Coastguard Worker   if (IsInHeadlessMode()) {
367*0a9764feSAndroid Build Coastguard Worker     // The pipeline can be nullptr in headless mode, so return the default
368*0a9764feSAndroid Build Coastguard Worker     // "normal" mode.
369*0a9764feSAndroid Build Coastguard Worker     return PanelOrientation::kModePanelOrientationNormal;
370*0a9764feSAndroid Build Coastguard Worker   }
371*0a9764feSAndroid Build Coastguard Worker 
372*0a9764feSAndroid Build Coastguard Worker   DrmDisplayPipeline &pipeline = GetPipe();
373*0a9764feSAndroid Build Coastguard Worker   if (pipeline.connector == nullptr || pipeline.connector->Get() == nullptr) {
374*0a9764feSAndroid Build Coastguard Worker     ALOGW(
375*0a9764feSAndroid Build Coastguard Worker         "No display pipeline present to query the panel orientation property.");
376*0a9764feSAndroid Build Coastguard Worker     return {};
377*0a9764feSAndroid Build Coastguard Worker   }
378*0a9764feSAndroid Build Coastguard Worker 
379*0a9764feSAndroid Build Coastguard Worker   return pipeline.connector->Get()->GetPanelOrientation();
380*0a9764feSAndroid Build Coastguard Worker }
381*0a9764feSAndroid Build Coastguard Worker 
ChosePreferredConfig()382*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::ChosePreferredConfig() {
383*0a9764feSAndroid Build Coastguard Worker   HWC2::Error err{};
384*0a9764feSAndroid Build Coastguard Worker   if (type_ == HWC2::DisplayType::Virtual) {
385*0a9764feSAndroid Build Coastguard Worker     configs_.GenFakeMode(virtual_disp_width_, virtual_disp_height_);
386*0a9764feSAndroid Build Coastguard Worker   } else if (!IsInHeadlessMode()) {
387*0a9764feSAndroid Build Coastguard Worker     err = configs_.Update(*pipeline_->connector->Get());
388*0a9764feSAndroid Build Coastguard Worker   } else {
389*0a9764feSAndroid Build Coastguard Worker     configs_.GenFakeMode(0, 0);
390*0a9764feSAndroid Build Coastguard Worker   }
391*0a9764feSAndroid Build Coastguard Worker   if (!IsInHeadlessMode() && err != HWC2::Error::None) {
392*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadDisplay;
393*0a9764feSAndroid Build Coastguard Worker   }
394*0a9764feSAndroid Build Coastguard Worker 
395*0a9764feSAndroid Build Coastguard Worker   return SetActiveConfig(configs_.preferred_config_id);
396*0a9764feSAndroid Build Coastguard Worker }
397*0a9764feSAndroid Build Coastguard Worker 
AcceptDisplayChanges()398*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::AcceptDisplayChanges() {
399*0a9764feSAndroid Build Coastguard Worker   for (std::pair<const hwc2_layer_t, HwcLayer> &l : layers_)
400*0a9764feSAndroid Build Coastguard Worker     l.second.AcceptTypeChange();
401*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
402*0a9764feSAndroid Build Coastguard Worker }
403*0a9764feSAndroid Build Coastguard Worker 
CreateLayer(hwc2_layer_t * layer)404*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::CreateLayer(hwc2_layer_t *layer) {
405*0a9764feSAndroid Build Coastguard Worker   layers_.emplace(static_cast<hwc2_layer_t>(layer_idx_), HwcLayer(this));
406*0a9764feSAndroid Build Coastguard Worker   *layer = static_cast<hwc2_layer_t>(layer_idx_);
407*0a9764feSAndroid Build Coastguard Worker   ++layer_idx_;
408*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
409*0a9764feSAndroid Build Coastguard Worker }
410*0a9764feSAndroid Build Coastguard Worker 
DestroyLayer(hwc2_layer_t layer)411*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::DestroyLayer(hwc2_layer_t layer) {
412*0a9764feSAndroid Build Coastguard Worker   if (!get_layer(layer)) {
413*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadLayer;
414*0a9764feSAndroid Build Coastguard Worker   }
415*0a9764feSAndroid Build Coastguard Worker 
416*0a9764feSAndroid Build Coastguard Worker   layers_.erase(layer);
417*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
418*0a9764feSAndroid Build Coastguard Worker }
419*0a9764feSAndroid Build Coastguard Worker 
GetActiveConfig(hwc2_config_t * config) const420*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::GetActiveConfig(hwc2_config_t *config) const {
421*0a9764feSAndroid Build Coastguard Worker   // If a config has been queued, it is considered the "active" config.
422*0a9764feSAndroid Build Coastguard Worker   const HwcDisplayConfig *hwc_config = GetLastRequestedConfig();
423*0a9764feSAndroid Build Coastguard Worker   if (hwc_config == nullptr)
424*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadConfig;
425*0a9764feSAndroid Build Coastguard Worker 
426*0a9764feSAndroid Build Coastguard Worker   *config = hwc_config->id;
427*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
428*0a9764feSAndroid Build Coastguard Worker }
429*0a9764feSAndroid Build Coastguard Worker 
GetChangedCompositionTypes(uint32_t * num_elements,hwc2_layer_t * layers,int32_t * types)430*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::GetChangedCompositionTypes(uint32_t *num_elements,
431*0a9764feSAndroid Build Coastguard Worker                                                    hwc2_layer_t *layers,
432*0a9764feSAndroid Build Coastguard Worker                                                    int32_t *types) {
433*0a9764feSAndroid Build Coastguard Worker   if (IsInHeadlessMode()) {
434*0a9764feSAndroid Build Coastguard Worker     *num_elements = 0;
435*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::None;
436*0a9764feSAndroid Build Coastguard Worker   }
437*0a9764feSAndroid Build Coastguard Worker 
438*0a9764feSAndroid Build Coastguard Worker   uint32_t num_changes = 0;
439*0a9764feSAndroid Build Coastguard Worker   for (auto &l : layers_) {
440*0a9764feSAndroid Build Coastguard Worker     if (l.second.IsTypeChanged()) {
441*0a9764feSAndroid Build Coastguard Worker       if (layers && num_changes < *num_elements)
442*0a9764feSAndroid Build Coastguard Worker         layers[num_changes] = l.first;
443*0a9764feSAndroid Build Coastguard Worker       if (types && num_changes < *num_elements)
444*0a9764feSAndroid Build Coastguard Worker         types[num_changes] = static_cast<int32_t>(l.second.GetValidatedType());
445*0a9764feSAndroid Build Coastguard Worker       ++num_changes;
446*0a9764feSAndroid Build Coastguard Worker     }
447*0a9764feSAndroid Build Coastguard Worker   }
448*0a9764feSAndroid Build Coastguard Worker   if (!layers && !types)
449*0a9764feSAndroid Build Coastguard Worker     *num_elements = num_changes;
450*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
451*0a9764feSAndroid Build Coastguard Worker }
452*0a9764feSAndroid Build Coastguard Worker 
GetClientTargetSupport(uint32_t width,uint32_t height,int32_t,int32_t dataspace)453*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::GetClientTargetSupport(uint32_t width, uint32_t height,
454*0a9764feSAndroid Build Coastguard Worker                                                int32_t /*format*/,
455*0a9764feSAndroid Build Coastguard Worker                                                int32_t dataspace) {
456*0a9764feSAndroid Build Coastguard Worker   if (IsInHeadlessMode()) {
457*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::None;
458*0a9764feSAndroid Build Coastguard Worker   }
459*0a9764feSAndroid Build Coastguard Worker 
460*0a9764feSAndroid Build Coastguard Worker   auto min = pipeline_->device->GetMinResolution();
461*0a9764feSAndroid Build Coastguard Worker   auto max = pipeline_->device->GetMaxResolution();
462*0a9764feSAndroid Build Coastguard Worker 
463*0a9764feSAndroid Build Coastguard Worker   if (width < min.first || height < min.second)
464*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::Unsupported;
465*0a9764feSAndroid Build Coastguard Worker 
466*0a9764feSAndroid Build Coastguard Worker   if (width > max.first || height > max.second)
467*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::Unsupported;
468*0a9764feSAndroid Build Coastguard Worker 
469*0a9764feSAndroid Build Coastguard Worker   if (dataspace != HAL_DATASPACE_UNKNOWN)
470*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::Unsupported;
471*0a9764feSAndroid Build Coastguard Worker 
472*0a9764feSAndroid Build Coastguard Worker   // TODO(nobody): Validate format can be handled by either GL or planes
473*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
474*0a9764feSAndroid Build Coastguard Worker }
475*0a9764feSAndroid Build Coastguard Worker 
GetColorModes(uint32_t * num_modes,int32_t * modes)476*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::GetColorModes(uint32_t *num_modes, int32_t *modes) {
477*0a9764feSAndroid Build Coastguard Worker   if (!modes)
478*0a9764feSAndroid Build Coastguard Worker     *num_modes = 1;
479*0a9764feSAndroid Build Coastguard Worker 
480*0a9764feSAndroid Build Coastguard Worker   if (modes)
481*0a9764feSAndroid Build Coastguard Worker     *modes = HAL_COLOR_MODE_NATIVE;
482*0a9764feSAndroid Build Coastguard Worker 
483*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
484*0a9764feSAndroid Build Coastguard Worker }
485*0a9764feSAndroid Build Coastguard Worker 
GetDisplayAttribute(hwc2_config_t config,int32_t attribute_in,int32_t * value)486*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::GetDisplayAttribute(hwc2_config_t config,
487*0a9764feSAndroid Build Coastguard Worker                                             int32_t attribute_in,
488*0a9764feSAndroid Build Coastguard Worker                                             int32_t *value) {
489*0a9764feSAndroid Build Coastguard Worker   int conf = static_cast<int>(config);
490*0a9764feSAndroid Build Coastguard Worker 
491*0a9764feSAndroid Build Coastguard Worker   if (configs_.hwc_configs.count(conf) == 0) {
492*0a9764feSAndroid Build Coastguard Worker     ALOGE("Could not find mode #%d", conf);
493*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadConfig;
494*0a9764feSAndroid Build Coastguard Worker   }
495*0a9764feSAndroid Build Coastguard Worker 
496*0a9764feSAndroid Build Coastguard Worker   auto &hwc_config = configs_.hwc_configs[conf];
497*0a9764feSAndroid Build Coastguard Worker 
498*0a9764feSAndroid Build Coastguard Worker   static const int32_t kUmPerInch = 25400;
499*0a9764feSAndroid Build Coastguard Worker   auto mm_width = configs_.mm_width;
500*0a9764feSAndroid Build Coastguard Worker   auto attribute = static_cast<HWC2::Attribute>(attribute_in);
501*0a9764feSAndroid Build Coastguard Worker   switch (attribute) {
502*0a9764feSAndroid Build Coastguard Worker     case HWC2::Attribute::Width:
503*0a9764feSAndroid Build Coastguard Worker       *value = static_cast<int>(hwc_config.mode.GetRawMode().hdisplay);
504*0a9764feSAndroid Build Coastguard Worker       break;
505*0a9764feSAndroid Build Coastguard Worker     case HWC2::Attribute::Height:
506*0a9764feSAndroid Build Coastguard Worker       *value = static_cast<int>(hwc_config.mode.GetRawMode().vdisplay);
507*0a9764feSAndroid Build Coastguard Worker       break;
508*0a9764feSAndroid Build Coastguard Worker     case HWC2::Attribute::VsyncPeriod:
509*0a9764feSAndroid Build Coastguard Worker       // in nanoseconds
510*0a9764feSAndroid Build Coastguard Worker       *value = hwc_config.mode.GetVSyncPeriodNs();
511*0a9764feSAndroid Build Coastguard Worker       break;
512*0a9764feSAndroid Build Coastguard Worker     case HWC2::Attribute::DpiY:
513*0a9764feSAndroid Build Coastguard Worker       // ideally this should be vdisplay/mm_heigth, however mm_height
514*0a9764feSAndroid Build Coastguard Worker       // comes from edid parsing and is highly unreliable. Viewing the
515*0a9764feSAndroid Build Coastguard Worker       // rarity of anisotropic displays, falling back to a single value
516*0a9764feSAndroid Build Coastguard Worker       // for dpi yield more correct output.
517*0a9764feSAndroid Build Coastguard Worker     case HWC2::Attribute::DpiX:
518*0a9764feSAndroid Build Coastguard Worker       // Dots per 1000 inches
519*0a9764feSAndroid Build Coastguard Worker       *value = mm_width ? int(hwc_config.mode.GetRawMode().hdisplay *
520*0a9764feSAndroid Build Coastguard Worker                               kUmPerInch / mm_width)
521*0a9764feSAndroid Build Coastguard Worker                         : -1;
522*0a9764feSAndroid Build Coastguard Worker       break;
523*0a9764feSAndroid Build Coastguard Worker #if __ANDROID_API__ > 29
524*0a9764feSAndroid Build Coastguard Worker     case HWC2::Attribute::ConfigGroup:
525*0a9764feSAndroid Build Coastguard Worker       /* Dispite ConfigGroup is a part of HWC2.4 API, framework
526*0a9764feSAndroid Build Coastguard Worker        * able to request it even if service @2.1 is used */
527*0a9764feSAndroid Build Coastguard Worker       *value = int(hwc_config.group_id);
528*0a9764feSAndroid Build Coastguard Worker       break;
529*0a9764feSAndroid Build Coastguard Worker #endif
530*0a9764feSAndroid Build Coastguard Worker     default:
531*0a9764feSAndroid Build Coastguard Worker       *value = -1;
532*0a9764feSAndroid Build Coastguard Worker       return HWC2::Error::BadConfig;
533*0a9764feSAndroid Build Coastguard Worker   }
534*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
535*0a9764feSAndroid Build Coastguard Worker }
536*0a9764feSAndroid Build Coastguard Worker 
LegacyGetDisplayConfigs(uint32_t * num_configs,hwc2_config_t * configs)537*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::LegacyGetDisplayConfigs(uint32_t *num_configs,
538*0a9764feSAndroid Build Coastguard Worker                                                 hwc2_config_t *configs) {
539*0a9764feSAndroid Build Coastguard Worker   uint32_t idx = 0;
540*0a9764feSAndroid Build Coastguard Worker   for (auto &hwc_config : configs_.hwc_configs) {
541*0a9764feSAndroid Build Coastguard Worker     if (hwc_config.second.disabled) {
542*0a9764feSAndroid Build Coastguard Worker       continue;
543*0a9764feSAndroid Build Coastguard Worker     }
544*0a9764feSAndroid Build Coastguard Worker 
545*0a9764feSAndroid Build Coastguard Worker     if (configs != nullptr) {
546*0a9764feSAndroid Build Coastguard Worker       if (idx >= *num_configs) {
547*0a9764feSAndroid Build Coastguard Worker         break;
548*0a9764feSAndroid Build Coastguard Worker       }
549*0a9764feSAndroid Build Coastguard Worker       configs[idx] = hwc_config.second.id;
550*0a9764feSAndroid Build Coastguard Worker     }
551*0a9764feSAndroid Build Coastguard Worker 
552*0a9764feSAndroid Build Coastguard Worker     idx++;
553*0a9764feSAndroid Build Coastguard Worker   }
554*0a9764feSAndroid Build Coastguard Worker   *num_configs = idx;
555*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
556*0a9764feSAndroid Build Coastguard Worker }
557*0a9764feSAndroid Build Coastguard Worker 
GetDisplayName(uint32_t * size,char * name)558*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::GetDisplayName(uint32_t *size, char *name) {
559*0a9764feSAndroid Build Coastguard Worker   std::ostringstream stream;
560*0a9764feSAndroid Build Coastguard Worker   if (IsInHeadlessMode()) {
561*0a9764feSAndroid Build Coastguard Worker     stream << "null-display";
562*0a9764feSAndroid Build Coastguard Worker   } else {
563*0a9764feSAndroid Build Coastguard Worker     stream << "display-" << GetPipe().connector->Get()->GetId();
564*0a9764feSAndroid Build Coastguard Worker   }
565*0a9764feSAndroid Build Coastguard Worker   auto string = stream.str();
566*0a9764feSAndroid Build Coastguard Worker   auto length = string.length();
567*0a9764feSAndroid Build Coastguard Worker   if (!name) {
568*0a9764feSAndroid Build Coastguard Worker     *size = length;
569*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::None;
570*0a9764feSAndroid Build Coastguard Worker   }
571*0a9764feSAndroid Build Coastguard Worker 
572*0a9764feSAndroid Build Coastguard Worker   *size = std::min<uint32_t>(static_cast<uint32_t>(length - 1), *size);
573*0a9764feSAndroid Build Coastguard Worker   strncpy(name, string.c_str(), *size);
574*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
575*0a9764feSAndroid Build Coastguard Worker }
576*0a9764feSAndroid Build Coastguard Worker 
GetDisplayRequests(int32_t *,uint32_t * num_elements,hwc2_layer_t *,int32_t *)577*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::GetDisplayRequests(int32_t * /*display_requests*/,
578*0a9764feSAndroid Build Coastguard Worker                                            uint32_t *num_elements,
579*0a9764feSAndroid Build Coastguard Worker                                            hwc2_layer_t * /*layers*/,
580*0a9764feSAndroid Build Coastguard Worker                                            int32_t * /*layer_requests*/) {
581*0a9764feSAndroid Build Coastguard Worker   // TODO(nobody): I think virtual display should request
582*0a9764feSAndroid Build Coastguard Worker   //      HWC2_DISPLAY_REQUEST_WRITE_CLIENT_TARGET_TO_OUTPUT here
583*0a9764feSAndroid Build Coastguard Worker   *num_elements = 0;
584*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
585*0a9764feSAndroid Build Coastguard Worker }
586*0a9764feSAndroid Build Coastguard Worker 
GetDisplayType(int32_t * type)587*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::GetDisplayType(int32_t *type) {
588*0a9764feSAndroid Build Coastguard Worker   *type = static_cast<int32_t>(type_);
589*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
590*0a9764feSAndroid Build Coastguard Worker }
591*0a9764feSAndroid Build Coastguard Worker 
GetDozeSupport(int32_t * support)592*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::GetDozeSupport(int32_t *support) {
593*0a9764feSAndroid Build Coastguard Worker   *support = 0;
594*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
595*0a9764feSAndroid Build Coastguard Worker }
596*0a9764feSAndroid Build Coastguard Worker 
GetHdrCapabilities(uint32_t * num_types,int32_t *,float *,float *,float *)597*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::GetHdrCapabilities(uint32_t *num_types,
598*0a9764feSAndroid Build Coastguard Worker                                            int32_t * /*types*/,
599*0a9764feSAndroid Build Coastguard Worker                                            float * /*max_luminance*/,
600*0a9764feSAndroid Build Coastguard Worker                                            float * /*max_average_luminance*/,
601*0a9764feSAndroid Build Coastguard Worker                                            float * /*min_luminance*/) {
602*0a9764feSAndroid Build Coastguard Worker   *num_types = 0;
603*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
604*0a9764feSAndroid Build Coastguard Worker }
605*0a9764feSAndroid Build Coastguard Worker 
606*0a9764feSAndroid Build Coastguard Worker /* Find API details at:
607*0a9764feSAndroid Build Coastguard Worker  * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1767
608*0a9764feSAndroid Build Coastguard Worker  *
609*0a9764feSAndroid Build Coastguard Worker  * Called after PresentDisplay(), CLIENT is expecting release fence for the
610*0a9764feSAndroid Build Coastguard Worker  * prior buffer (not the one assigned to the layer at the moment).
611*0a9764feSAndroid Build Coastguard Worker  */
GetReleaseFences(uint32_t * num_elements,hwc2_layer_t * layers,int32_t * fences)612*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::GetReleaseFences(uint32_t *num_elements,
613*0a9764feSAndroid Build Coastguard Worker                                          hwc2_layer_t *layers,
614*0a9764feSAndroid Build Coastguard Worker                                          int32_t *fences) {
615*0a9764feSAndroid Build Coastguard Worker   if (IsInHeadlessMode()) {
616*0a9764feSAndroid Build Coastguard Worker     *num_elements = 0;
617*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::None;
618*0a9764feSAndroid Build Coastguard Worker   }
619*0a9764feSAndroid Build Coastguard Worker 
620*0a9764feSAndroid Build Coastguard Worker   uint32_t num_layers = 0;
621*0a9764feSAndroid Build Coastguard Worker 
622*0a9764feSAndroid Build Coastguard Worker   for (auto &l : layers_) {
623*0a9764feSAndroid Build Coastguard Worker     if (!l.second.GetPriorBufferScanOutFlag() || !present_fence_) {
624*0a9764feSAndroid Build Coastguard Worker       continue;
625*0a9764feSAndroid Build Coastguard Worker     }
626*0a9764feSAndroid Build Coastguard Worker 
627*0a9764feSAndroid Build Coastguard Worker     ++num_layers;
628*0a9764feSAndroid Build Coastguard Worker 
629*0a9764feSAndroid Build Coastguard Worker     if (layers == nullptr || fences == nullptr)
630*0a9764feSAndroid Build Coastguard Worker       continue;
631*0a9764feSAndroid Build Coastguard Worker 
632*0a9764feSAndroid Build Coastguard Worker     if (num_layers > *num_elements) {
633*0a9764feSAndroid Build Coastguard Worker       ALOGW("Overflow num_elements %d/%d", num_layers, *num_elements);
634*0a9764feSAndroid Build Coastguard Worker       return HWC2::Error::None;
635*0a9764feSAndroid Build Coastguard Worker     }
636*0a9764feSAndroid Build Coastguard Worker 
637*0a9764feSAndroid Build Coastguard Worker     layers[num_layers - 1] = l.first;
638*0a9764feSAndroid Build Coastguard Worker     fences[num_layers - 1] = DupFd(present_fence_);
639*0a9764feSAndroid Build Coastguard Worker   }
640*0a9764feSAndroid Build Coastguard Worker   *num_elements = num_layers;
641*0a9764feSAndroid Build Coastguard Worker 
642*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
643*0a9764feSAndroid Build Coastguard Worker }
644*0a9764feSAndroid Build Coastguard Worker 
CreateModesetCommit(const HwcDisplayConfig * config,const std::optional<LayerData> & modeset_layer)645*0a9764feSAndroid Build Coastguard Worker AtomicCommitArgs HwcDisplay::CreateModesetCommit(
646*0a9764feSAndroid Build Coastguard Worker     const HwcDisplayConfig *config,
647*0a9764feSAndroid Build Coastguard Worker     const std::optional<LayerData> &modeset_layer) {
648*0a9764feSAndroid Build Coastguard Worker   AtomicCommitArgs args{};
649*0a9764feSAndroid Build Coastguard Worker 
650*0a9764feSAndroid Build Coastguard Worker   args.color_matrix = color_matrix_;
651*0a9764feSAndroid Build Coastguard Worker   args.content_type = content_type_;
652*0a9764feSAndroid Build Coastguard Worker   args.colorspace = colorspace_;
653*0a9764feSAndroid Build Coastguard Worker 
654*0a9764feSAndroid Build Coastguard Worker   std::vector<LayerData> composition_layers;
655*0a9764feSAndroid Build Coastguard Worker   if (modeset_layer) {
656*0a9764feSAndroid Build Coastguard Worker     composition_layers.emplace_back(modeset_layer.value());
657*0a9764feSAndroid Build Coastguard Worker   }
658*0a9764feSAndroid Build Coastguard Worker 
659*0a9764feSAndroid Build Coastguard Worker   if (composition_layers.empty()) {
660*0a9764feSAndroid Build Coastguard Worker     ALOGW("Attempting to create a modeset commit without a layer.");
661*0a9764feSAndroid Build Coastguard Worker   }
662*0a9764feSAndroid Build Coastguard Worker 
663*0a9764feSAndroid Build Coastguard Worker   args.display_mode = config->mode;
664*0a9764feSAndroid Build Coastguard Worker   args.active = true;
665*0a9764feSAndroid Build Coastguard Worker   args.composition = DrmKmsPlan::CreateDrmKmsPlan(GetPipe(),
666*0a9764feSAndroid Build Coastguard Worker                                                   std::move(
667*0a9764feSAndroid Build Coastguard Worker                                                       composition_layers));
668*0a9764feSAndroid Build Coastguard Worker   ALOGW_IF(!args.composition, "No composition for blocking modeset");
669*0a9764feSAndroid Build Coastguard Worker 
670*0a9764feSAndroid Build Coastguard Worker   return args;
671*0a9764feSAndroid Build Coastguard Worker }
672*0a9764feSAndroid Build Coastguard Worker 
CreateComposition(AtomicCommitArgs & a_args)673*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) {
674*0a9764feSAndroid Build Coastguard Worker   if (IsInHeadlessMode()) {
675*0a9764feSAndroid Build Coastguard Worker     ALOGE("%s: Display is in headless mode, should never reach here", __func__);
676*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::None;
677*0a9764feSAndroid Build Coastguard Worker   }
678*0a9764feSAndroid Build Coastguard Worker 
679*0a9764feSAndroid Build Coastguard Worker   a_args.color_matrix = color_matrix_;
680*0a9764feSAndroid Build Coastguard Worker   a_args.content_type = content_type_;
681*0a9764feSAndroid Build Coastguard Worker   a_args.colorspace = colorspace_;
682*0a9764feSAndroid Build Coastguard Worker 
683*0a9764feSAndroid Build Coastguard Worker   uint32_t prev_vperiod_ns = 0;
684*0a9764feSAndroid Build Coastguard Worker   GetDisplayVsyncPeriod(&prev_vperiod_ns);
685*0a9764feSAndroid Build Coastguard Worker 
686*0a9764feSAndroid Build Coastguard Worker   auto mode_update_commited_ = false;
687*0a9764feSAndroid Build Coastguard Worker   if (staged_mode_config_id_ &&
688*0a9764feSAndroid Build Coastguard Worker       staged_mode_change_time_ <= ResourceManager::GetTimeMonotonicNs()) {
689*0a9764feSAndroid Build Coastguard Worker     const HwcDisplayConfig *staged_config = GetConfig(
690*0a9764feSAndroid Build Coastguard Worker         staged_mode_config_id_.value());
691*0a9764feSAndroid Build Coastguard Worker     if (staged_config == nullptr) {
692*0a9764feSAndroid Build Coastguard Worker       return HWC2::Error::BadConfig;
693*0a9764feSAndroid Build Coastguard Worker     }
694*0a9764feSAndroid Build Coastguard Worker     client_layer_.SetLayerDisplayFrame(
695*0a9764feSAndroid Build Coastguard Worker         (hwc_rect_t){.left = 0,
696*0a9764feSAndroid Build Coastguard Worker                      .top = 0,
697*0a9764feSAndroid Build Coastguard Worker                      .right = int(staged_config->mode.GetRawMode().hdisplay),
698*0a9764feSAndroid Build Coastguard Worker                      .bottom = int(staged_config->mode.GetRawMode().vdisplay)});
699*0a9764feSAndroid Build Coastguard Worker 
700*0a9764feSAndroid Build Coastguard Worker     configs_.active_config_id = staged_mode_config_id_.value();
701*0a9764feSAndroid Build Coastguard Worker 
702*0a9764feSAndroid Build Coastguard Worker     a_args.display_mode = staged_config->mode;
703*0a9764feSAndroid Build Coastguard Worker     if (!a_args.test_only) {
704*0a9764feSAndroid Build Coastguard Worker       mode_update_commited_ = true;
705*0a9764feSAndroid Build Coastguard Worker     }
706*0a9764feSAndroid Build Coastguard Worker   }
707*0a9764feSAndroid Build Coastguard Worker 
708*0a9764feSAndroid Build Coastguard Worker   // order the layers by z-order
709*0a9764feSAndroid Build Coastguard Worker   bool use_client_layer = false;
710*0a9764feSAndroid Build Coastguard Worker   uint32_t client_z_order = UINT32_MAX;
711*0a9764feSAndroid Build Coastguard Worker   std::map<uint32_t, HwcLayer *> z_map;
712*0a9764feSAndroid Build Coastguard Worker   for (std::pair<const hwc2_layer_t, HwcLayer> &l : layers_) {
713*0a9764feSAndroid Build Coastguard Worker     switch (l.second.GetValidatedType()) {
714*0a9764feSAndroid Build Coastguard Worker       case HWC2::Composition::Device:
715*0a9764feSAndroid Build Coastguard Worker         z_map.emplace(l.second.GetZOrder(), &l.second);
716*0a9764feSAndroid Build Coastguard Worker         break;
717*0a9764feSAndroid Build Coastguard Worker       case HWC2::Composition::Client:
718*0a9764feSAndroid Build Coastguard Worker         // Place it at the z_order of the lowest client layer
719*0a9764feSAndroid Build Coastguard Worker         use_client_layer = true;
720*0a9764feSAndroid Build Coastguard Worker         client_z_order = std::min(client_z_order, l.second.GetZOrder());
721*0a9764feSAndroid Build Coastguard Worker         break;
722*0a9764feSAndroid Build Coastguard Worker       default:
723*0a9764feSAndroid Build Coastguard Worker         continue;
724*0a9764feSAndroid Build Coastguard Worker     }
725*0a9764feSAndroid Build Coastguard Worker   }
726*0a9764feSAndroid Build Coastguard Worker   if (use_client_layer)
727*0a9764feSAndroid Build Coastguard Worker     z_map.emplace(client_z_order, &client_layer_);
728*0a9764feSAndroid Build Coastguard Worker 
729*0a9764feSAndroid Build Coastguard Worker   if (z_map.empty())
730*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadLayer;
731*0a9764feSAndroid Build Coastguard Worker 
732*0a9764feSAndroid Build Coastguard Worker   std::vector<LayerData> composition_layers;
733*0a9764feSAndroid Build Coastguard Worker 
734*0a9764feSAndroid Build Coastguard Worker   /* Import & populate */
735*0a9764feSAndroid Build Coastguard Worker   for (std::pair<const uint32_t, HwcLayer *> &l : z_map) {
736*0a9764feSAndroid Build Coastguard Worker     l.second->PopulateLayerData();
737*0a9764feSAndroid Build Coastguard Worker   }
738*0a9764feSAndroid Build Coastguard Worker 
739*0a9764feSAndroid Build Coastguard Worker   // now that they're ordered by z, add them to the composition
740*0a9764feSAndroid Build Coastguard Worker   for (std::pair<const uint32_t, HwcLayer *> &l : z_map) {
741*0a9764feSAndroid Build Coastguard Worker     if (!l.second->IsLayerUsableAsDevice()) {
742*0a9764feSAndroid Build Coastguard Worker       /* This will be normally triggered on validation of the first frame
743*0a9764feSAndroid Build Coastguard Worker        * containing CLIENT layer. At this moment client buffer is not yet
744*0a9764feSAndroid Build Coastguard Worker        * provided by the CLIENT.
745*0a9764feSAndroid Build Coastguard Worker        * This may be triggered once in HwcLayer lifecycle in case FB can't be
746*0a9764feSAndroid Build Coastguard Worker        * imported. For example when non-contiguous buffer is imported into
747*0a9764feSAndroid Build Coastguard Worker        * contiguous-only DRM/KMS driver.
748*0a9764feSAndroid Build Coastguard Worker        */
749*0a9764feSAndroid Build Coastguard Worker       return HWC2::Error::BadLayer;
750*0a9764feSAndroid Build Coastguard Worker     }
751*0a9764feSAndroid Build Coastguard Worker     composition_layers.emplace_back(l.second->GetLayerData());
752*0a9764feSAndroid Build Coastguard Worker   }
753*0a9764feSAndroid Build Coastguard Worker 
754*0a9764feSAndroid Build Coastguard Worker   /* Store plan to ensure shared planes won't be stolen by other display
755*0a9764feSAndroid Build Coastguard Worker    * in between of ValidateDisplay() and PresentDisplay() calls
756*0a9764feSAndroid Build Coastguard Worker    */
757*0a9764feSAndroid Build Coastguard Worker   current_plan_ = DrmKmsPlan::CreateDrmKmsPlan(GetPipe(),
758*0a9764feSAndroid Build Coastguard Worker                                                std::move(composition_layers));
759*0a9764feSAndroid Build Coastguard Worker 
760*0a9764feSAndroid Build Coastguard Worker   if (type_ == HWC2::DisplayType::Virtual) {
761*0a9764feSAndroid Build Coastguard Worker     a_args.writeback_fb = writeback_layer_->GetLayerData().fb;
762*0a9764feSAndroid Build Coastguard Worker     a_args.writeback_release_fence = writeback_layer_->GetLayerData()
763*0a9764feSAndroid Build Coastguard Worker                                          .acquire_fence;
764*0a9764feSAndroid Build Coastguard Worker   }
765*0a9764feSAndroid Build Coastguard Worker 
766*0a9764feSAndroid Build Coastguard Worker   if (!current_plan_) {
767*0a9764feSAndroid Build Coastguard Worker     ALOGE_IF(!a_args.test_only, "Failed to create DrmKmsPlan");
768*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadConfig;
769*0a9764feSAndroid Build Coastguard Worker   }
770*0a9764feSAndroid Build Coastguard Worker 
771*0a9764feSAndroid Build Coastguard Worker   a_args.composition = current_plan_;
772*0a9764feSAndroid Build Coastguard Worker 
773*0a9764feSAndroid Build Coastguard Worker   auto ret = GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args);
774*0a9764feSAndroid Build Coastguard Worker 
775*0a9764feSAndroid Build Coastguard Worker   if (ret) {
776*0a9764feSAndroid Build Coastguard Worker     ALOGE_IF(!a_args.test_only, "Failed to apply the frame composition ret=%d", ret);
777*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadParameter;
778*0a9764feSAndroid Build Coastguard Worker   }
779*0a9764feSAndroid Build Coastguard Worker 
780*0a9764feSAndroid Build Coastguard Worker   if (mode_update_commited_) {
781*0a9764feSAndroid Build Coastguard Worker     staged_mode_config_id_.reset();
782*0a9764feSAndroid Build Coastguard Worker     vsync_tracking_en_ = false;
783*0a9764feSAndroid Build Coastguard Worker     if (last_vsync_ts_ != 0) {
784*0a9764feSAndroid Build Coastguard Worker       hwc_->SendVsyncPeriodTimingChangedEventToClient(handle_,
785*0a9764feSAndroid Build Coastguard Worker                                                       last_vsync_ts_ +
786*0a9764feSAndroid Build Coastguard Worker                                                           prev_vperiod_ns);
787*0a9764feSAndroid Build Coastguard Worker     }
788*0a9764feSAndroid Build Coastguard Worker   }
789*0a9764feSAndroid Build Coastguard Worker 
790*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
791*0a9764feSAndroid Build Coastguard Worker }
792*0a9764feSAndroid Build Coastguard Worker 
793*0a9764feSAndroid Build Coastguard Worker /* Find API details at:
794*0a9764feSAndroid Build Coastguard Worker  * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1805
795*0a9764feSAndroid Build Coastguard Worker  */
PresentDisplay(int32_t * out_present_fence)796*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::PresentDisplay(int32_t *out_present_fence) {
797*0a9764feSAndroid Build Coastguard Worker   if (IsInHeadlessMode()) {
798*0a9764feSAndroid Build Coastguard Worker     *out_present_fence = -1;
799*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::None;
800*0a9764feSAndroid Build Coastguard Worker   }
801*0a9764feSAndroid Build Coastguard Worker   HWC2::Error ret{};
802*0a9764feSAndroid Build Coastguard Worker 
803*0a9764feSAndroid Build Coastguard Worker   ++total_stats_.total_frames_;
804*0a9764feSAndroid Build Coastguard Worker 
805*0a9764feSAndroid Build Coastguard Worker   AtomicCommitArgs a_args{};
806*0a9764feSAndroid Build Coastguard Worker   ret = CreateComposition(a_args);
807*0a9764feSAndroid Build Coastguard Worker 
808*0a9764feSAndroid Build Coastguard Worker   if (ret != HWC2::Error::None)
809*0a9764feSAndroid Build Coastguard Worker     ++total_stats_.failed_kms_present_;
810*0a9764feSAndroid Build Coastguard Worker 
811*0a9764feSAndroid Build Coastguard Worker   if (ret == HWC2::Error::BadLayer) {
812*0a9764feSAndroid Build Coastguard Worker     // Can we really have no client or device layers?
813*0a9764feSAndroid Build Coastguard Worker     *out_present_fence = -1;
814*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::None;
815*0a9764feSAndroid Build Coastguard Worker   }
816*0a9764feSAndroid Build Coastguard Worker   if (ret != HWC2::Error::None)
817*0a9764feSAndroid Build Coastguard Worker     return ret;
818*0a9764feSAndroid Build Coastguard Worker 
819*0a9764feSAndroid Build Coastguard Worker   this->present_fence_ = a_args.out_fence;
820*0a9764feSAndroid Build Coastguard Worker   *out_present_fence = DupFd(a_args.out_fence);
821*0a9764feSAndroid Build Coastguard Worker 
822*0a9764feSAndroid Build Coastguard Worker   // Reset the color matrix so we don't apply it over and over again.
823*0a9764feSAndroid Build Coastguard Worker   color_matrix_ = {};
824*0a9764feSAndroid Build Coastguard Worker 
825*0a9764feSAndroid Build Coastguard Worker   ++frame_no_;
826*0a9764feSAndroid Build Coastguard Worker 
827*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
828*0a9764feSAndroid Build Coastguard Worker }
829*0a9764feSAndroid Build Coastguard Worker 
SetActiveConfigInternal(uint32_t config,int64_t change_time)830*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::SetActiveConfigInternal(uint32_t config,
831*0a9764feSAndroid Build Coastguard Worker                                                 int64_t change_time) {
832*0a9764feSAndroid Build Coastguard Worker   if (configs_.hwc_configs.count(config) == 0) {
833*0a9764feSAndroid Build Coastguard Worker     ALOGE("Could not find active mode for %u", config);
834*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadConfig;
835*0a9764feSAndroid Build Coastguard Worker   }
836*0a9764feSAndroid Build Coastguard Worker 
837*0a9764feSAndroid Build Coastguard Worker   staged_mode_change_time_ = change_time;
838*0a9764feSAndroid Build Coastguard Worker   staged_mode_config_id_ = config;
839*0a9764feSAndroid Build Coastguard Worker 
840*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
841*0a9764feSAndroid Build Coastguard Worker }
842*0a9764feSAndroid Build Coastguard Worker 
SetActiveConfig(hwc2_config_t config)843*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::SetActiveConfig(hwc2_config_t config) {
844*0a9764feSAndroid Build Coastguard Worker   return SetActiveConfigInternal(config, ResourceManager::GetTimeMonotonicNs());
845*0a9764feSAndroid Build Coastguard Worker }
846*0a9764feSAndroid Build Coastguard Worker 
847*0a9764feSAndroid Build Coastguard Worker /* Find API details at:
848*0a9764feSAndroid Build Coastguard Worker  * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1861
849*0a9764feSAndroid Build Coastguard Worker  */
SetClientTarget(buffer_handle_t target,int32_t acquire_fence,int32_t dataspace,hwc_region_t)850*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::SetClientTarget(buffer_handle_t target,
851*0a9764feSAndroid Build Coastguard Worker                                         int32_t acquire_fence,
852*0a9764feSAndroid Build Coastguard Worker                                         int32_t dataspace,
853*0a9764feSAndroid Build Coastguard Worker                                         hwc_region_t /*damage*/) {
854*0a9764feSAndroid Build Coastguard Worker   client_layer_.SetLayerBuffer(target, acquire_fence);
855*0a9764feSAndroid Build Coastguard Worker   client_layer_.SetLayerDataspace(dataspace);
856*0a9764feSAndroid Build Coastguard Worker 
857*0a9764feSAndroid Build Coastguard Worker   /*
858*0a9764feSAndroid Build Coastguard Worker    * target can be nullptr, this does mean the Composer Service is calling
859*0a9764feSAndroid Build Coastguard Worker    * cleanDisplayResources() on after receiving HOTPLUG event. See more at:
860*0a9764feSAndroid Build Coastguard Worker    * https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h;l=350;drc=944b68180b008456ed2eb4d4d329e33b19bd5166
861*0a9764feSAndroid Build Coastguard Worker    */
862*0a9764feSAndroid Build Coastguard Worker   if (target == nullptr) {
863*0a9764feSAndroid Build Coastguard Worker     client_layer_.SwChainClearCache();
864*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::None;
865*0a9764feSAndroid Build Coastguard Worker   }
866*0a9764feSAndroid Build Coastguard Worker 
867*0a9764feSAndroid Build Coastguard Worker   if (IsInHeadlessMode()) {
868*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::None;
869*0a9764feSAndroid Build Coastguard Worker   }
870*0a9764feSAndroid Build Coastguard Worker 
871*0a9764feSAndroid Build Coastguard Worker   client_layer_.PopulateLayerData();
872*0a9764feSAndroid Build Coastguard Worker   if (!client_layer_.IsLayerUsableAsDevice()) {
873*0a9764feSAndroid Build Coastguard Worker     ALOGE("Client layer must be always usable by DRM/KMS");
874*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadLayer;
875*0a9764feSAndroid Build Coastguard Worker   }
876*0a9764feSAndroid Build Coastguard Worker 
877*0a9764feSAndroid Build Coastguard Worker   auto &bi = client_layer_.GetLayerData().bi;
878*0a9764feSAndroid Build Coastguard Worker   if (!bi) {
879*0a9764feSAndroid Build Coastguard Worker     ALOGE("%s: Invalid state", __func__);
880*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadLayer;
881*0a9764feSAndroid Build Coastguard Worker   }
882*0a9764feSAndroid Build Coastguard Worker 
883*0a9764feSAndroid Build Coastguard Worker   auto source_crop = (hwc_frect_t){.left = 0.0F,
884*0a9764feSAndroid Build Coastguard Worker                                    .top = 0.0F,
885*0a9764feSAndroid Build Coastguard Worker                                    .right = static_cast<float>(bi->width),
886*0a9764feSAndroid Build Coastguard Worker                                    .bottom = static_cast<float>(bi->height)};
887*0a9764feSAndroid Build Coastguard Worker   client_layer_.SetLayerSourceCrop(source_crop);
888*0a9764feSAndroid Build Coastguard Worker 
889*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
890*0a9764feSAndroid Build Coastguard Worker }
891*0a9764feSAndroid Build Coastguard Worker 
SetColorMode(int32_t mode)892*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::SetColorMode(int32_t mode) {
893*0a9764feSAndroid Build Coastguard Worker   /* Maps to the Colorspace DRM connector property:
894*0a9764feSAndroid Build Coastguard Worker    * https://elixir.bootlin.com/linux/v6.11/source/include/drm/drm_connector.h#L538
895*0a9764feSAndroid Build Coastguard Worker    */
896*0a9764feSAndroid Build Coastguard Worker   if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_DISPLAY_P3)
897*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadParameter;
898*0a9764feSAndroid Build Coastguard Worker 
899*0a9764feSAndroid Build Coastguard Worker   switch (mode) {
900*0a9764feSAndroid Build Coastguard Worker     case HAL_COLOR_MODE_NATIVE:
901*0a9764feSAndroid Build Coastguard Worker       colorspace_ = Colorspace::kDefault;
902*0a9764feSAndroid Build Coastguard Worker       break;
903*0a9764feSAndroid Build Coastguard Worker     case HAL_COLOR_MODE_STANDARD_BT601_625:
904*0a9764feSAndroid Build Coastguard Worker     case HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED:
905*0a9764feSAndroid Build Coastguard Worker     case HAL_COLOR_MODE_STANDARD_BT601_525:
906*0a9764feSAndroid Build Coastguard Worker     case HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED:
907*0a9764feSAndroid Build Coastguard Worker       // The DP spec does not say whether this is the 525 or the 625 line version.
908*0a9764feSAndroid Build Coastguard Worker       colorspace_ = Colorspace::kBt601Ycc;
909*0a9764feSAndroid Build Coastguard Worker       break;
910*0a9764feSAndroid Build Coastguard Worker     case HAL_COLOR_MODE_STANDARD_BT709:
911*0a9764feSAndroid Build Coastguard Worker     case HAL_COLOR_MODE_SRGB:
912*0a9764feSAndroid Build Coastguard Worker       colorspace_ = Colorspace::kBt709Ycc;
913*0a9764feSAndroid Build Coastguard Worker       break;
914*0a9764feSAndroid Build Coastguard Worker     case HAL_COLOR_MODE_DCI_P3:
915*0a9764feSAndroid Build Coastguard Worker     case HAL_COLOR_MODE_DISPLAY_P3:
916*0a9764feSAndroid Build Coastguard Worker       colorspace_ = Colorspace::kDciP3RgbD65;
917*0a9764feSAndroid Build Coastguard Worker       break;
918*0a9764feSAndroid Build Coastguard Worker     case HAL_COLOR_MODE_ADOBE_RGB:
919*0a9764feSAndroid Build Coastguard Worker     default:
920*0a9764feSAndroid Build Coastguard Worker       return HWC2::Error::Unsupported;
921*0a9764feSAndroid Build Coastguard Worker   }
922*0a9764feSAndroid Build Coastguard Worker 
923*0a9764feSAndroid Build Coastguard Worker   color_mode_ = mode;
924*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
925*0a9764feSAndroid Build Coastguard Worker }
926*0a9764feSAndroid Build Coastguard Worker 
927*0a9764feSAndroid Build Coastguard Worker #include <xf86drmMode.h>
928*0a9764feSAndroid Build Coastguard Worker 
To3132FixPt(float in)929*0a9764feSAndroid Build Coastguard Worker static uint64_t To3132FixPt(float in) {
930*0a9764feSAndroid Build Coastguard Worker   constexpr uint64_t kSignMask = (1ULL << 63);
931*0a9764feSAndroid Build Coastguard Worker   constexpr uint64_t kValueMask = ~(1ULL << 63);
932*0a9764feSAndroid Build Coastguard Worker   constexpr auto kValueScale = static_cast<float>(1ULL << 32);
933*0a9764feSAndroid Build Coastguard Worker   if (in < 0)
934*0a9764feSAndroid Build Coastguard Worker     return (static_cast<uint64_t>(-in * kValueScale) & kValueMask) | kSignMask;
935*0a9764feSAndroid Build Coastguard Worker   return static_cast<uint64_t>(in * kValueScale) & kValueMask;
936*0a9764feSAndroid Build Coastguard Worker }
937*0a9764feSAndroid Build Coastguard Worker 
SetColorTransform(const float * matrix,int32_t hint)938*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::SetColorTransform(const float *matrix, int32_t hint) {
939*0a9764feSAndroid Build Coastguard Worker   if (hint < HAL_COLOR_TRANSFORM_IDENTITY ||
940*0a9764feSAndroid Build Coastguard Worker       hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA)
941*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadParameter;
942*0a9764feSAndroid Build Coastguard Worker 
943*0a9764feSAndroid Build Coastguard Worker   if (!matrix && hint == HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX)
944*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadParameter;
945*0a9764feSAndroid Build Coastguard Worker 
946*0a9764feSAndroid Build Coastguard Worker   color_transform_hint_ = static_cast<android_color_transform_t>(hint);
947*0a9764feSAndroid Build Coastguard Worker 
948*0a9764feSAndroid Build Coastguard Worker   if (IsInHeadlessMode())
949*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::None;
950*0a9764feSAndroid Build Coastguard Worker 
951*0a9764feSAndroid Build Coastguard Worker   if (!GetPipe().crtc->Get()->GetCtmProperty())
952*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::None;
953*0a9764feSAndroid Build Coastguard Worker 
954*0a9764feSAndroid Build Coastguard Worker   switch (color_transform_hint_) {
955*0a9764feSAndroid Build Coastguard Worker     case HAL_COLOR_TRANSFORM_IDENTITY:
956*0a9764feSAndroid Build Coastguard Worker       SetColorMatrixToIdentity();
957*0a9764feSAndroid Build Coastguard Worker       break;
958*0a9764feSAndroid Build Coastguard Worker     case HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX:
959*0a9764feSAndroid Build Coastguard Worker       // Without HW support, we cannot correctly process matrices with an offset.
960*0a9764feSAndroid Build Coastguard Worker       for (int i = 12; i < 14; i++) {
961*0a9764feSAndroid Build Coastguard Worker         if (matrix[i] != 0.F)
962*0a9764feSAndroid Build Coastguard Worker           return HWC2::Error::Unsupported;
963*0a9764feSAndroid Build Coastguard Worker       }
964*0a9764feSAndroid Build Coastguard Worker 
965*0a9764feSAndroid Build Coastguard Worker       /* HAL provides a 4x4 float type matrix:
966*0a9764feSAndroid Build Coastguard Worker        * | 0  1  2  3|
967*0a9764feSAndroid Build Coastguard Worker        * | 4  5  6  7|
968*0a9764feSAndroid Build Coastguard Worker        * | 8  9 10 11|
969*0a9764feSAndroid Build Coastguard Worker        * |12 13 14 15|
970*0a9764feSAndroid Build Coastguard Worker        *
971*0a9764feSAndroid Build Coastguard Worker        * R_out = R*0 + G*4 + B*8 + 12
972*0a9764feSAndroid Build Coastguard Worker        * G_out = R*1 + G*5 + B*9 + 13
973*0a9764feSAndroid Build Coastguard Worker        * B_out = R*2 + G*6 + B*10 + 14
974*0a9764feSAndroid Build Coastguard Worker        *
975*0a9764feSAndroid Build Coastguard Worker        * DRM expects a 3x3 s31.32 fixed point matrix:
976*0a9764feSAndroid Build Coastguard Worker        * out   matrix    in
977*0a9764feSAndroid Build Coastguard Worker        * |R|   |0 1 2|   |R|
978*0a9764feSAndroid Build Coastguard Worker        * |G| = |3 4 5| x |G|
979*0a9764feSAndroid Build Coastguard Worker        * |B|   |6 7 8|   |B|
980*0a9764feSAndroid Build Coastguard Worker        *
981*0a9764feSAndroid Build Coastguard Worker        * R_out = R*0 + G*1 + B*2
982*0a9764feSAndroid Build Coastguard Worker        * G_out = R*3 + G*4 + B*5
983*0a9764feSAndroid Build Coastguard Worker        * B_out = R*6 + G*7 + B*8
984*0a9764feSAndroid Build Coastguard Worker        */
985*0a9764feSAndroid Build Coastguard Worker       color_matrix_ = std::make_shared<drm_color_ctm>();
986*0a9764feSAndroid Build Coastguard Worker       for (int i = 0; i < kCtmCols; i++) {
987*0a9764feSAndroid Build Coastguard Worker         for (int j = 0; j < kCtmRows; j++) {
988*0a9764feSAndroid Build Coastguard Worker           constexpr int kInCtmRows = 4;
989*0a9764feSAndroid Build Coastguard Worker           color_matrix_->matrix[i * kCtmRows + j] = To3132FixPt(matrix[j * kInCtmRows + i]);
990*0a9764feSAndroid Build Coastguard Worker         }
991*0a9764feSAndroid Build Coastguard Worker       }
992*0a9764feSAndroid Build Coastguard Worker       break;
993*0a9764feSAndroid Build Coastguard Worker     default:
994*0a9764feSAndroid Build Coastguard Worker       return HWC2::Error::Unsupported;
995*0a9764feSAndroid Build Coastguard Worker   }
996*0a9764feSAndroid Build Coastguard Worker 
997*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
998*0a9764feSAndroid Build Coastguard Worker }
999*0a9764feSAndroid Build Coastguard Worker 
CtmByGpu()1000*0a9764feSAndroid Build Coastguard Worker bool HwcDisplay::CtmByGpu() {
1001*0a9764feSAndroid Build Coastguard Worker   if (color_transform_hint_ == HAL_COLOR_TRANSFORM_IDENTITY)
1002*0a9764feSAndroid Build Coastguard Worker     return false;
1003*0a9764feSAndroid Build Coastguard Worker 
1004*0a9764feSAndroid Build Coastguard Worker   if (GetPipe().crtc->Get()->GetCtmProperty())
1005*0a9764feSAndroid Build Coastguard Worker     return false;
1006*0a9764feSAndroid Build Coastguard Worker 
1007*0a9764feSAndroid Build Coastguard Worker   if (GetHwc()->GetResMan().GetCtmHandling() == CtmHandling::kDrmOrIgnore)
1008*0a9764feSAndroid Build Coastguard Worker     return false;
1009*0a9764feSAndroid Build Coastguard Worker 
1010*0a9764feSAndroid Build Coastguard Worker   return true;
1011*0a9764feSAndroid Build Coastguard Worker }
1012*0a9764feSAndroid Build Coastguard Worker 
SetOutputBuffer(buffer_handle_t buffer,int32_t release_fence)1013*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::SetOutputBuffer(buffer_handle_t buffer,
1014*0a9764feSAndroid Build Coastguard Worker                                         int32_t release_fence) {
1015*0a9764feSAndroid Build Coastguard Worker   writeback_layer_->SetLayerBuffer(buffer, release_fence);
1016*0a9764feSAndroid Build Coastguard Worker   writeback_layer_->PopulateLayerData();
1017*0a9764feSAndroid Build Coastguard Worker   if (!writeback_layer_->IsLayerUsableAsDevice()) {
1018*0a9764feSAndroid Build Coastguard Worker     ALOGE("Output layer must be always usable by DRM/KMS");
1019*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadLayer;
1020*0a9764feSAndroid Build Coastguard Worker   }
1021*0a9764feSAndroid Build Coastguard Worker   /* TODO: Check if format is supported by writeback connector */
1022*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
1023*0a9764feSAndroid Build Coastguard Worker }
1024*0a9764feSAndroid Build Coastguard Worker 
SetPowerMode(int32_t mode_in)1025*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::SetPowerMode(int32_t mode_in) {
1026*0a9764feSAndroid Build Coastguard Worker   auto mode = static_cast<HWC2::PowerMode>(mode_in);
1027*0a9764feSAndroid Build Coastguard Worker 
1028*0a9764feSAndroid Build Coastguard Worker   AtomicCommitArgs a_args{};
1029*0a9764feSAndroid Build Coastguard Worker 
1030*0a9764feSAndroid Build Coastguard Worker   switch (mode) {
1031*0a9764feSAndroid Build Coastguard Worker     case HWC2::PowerMode::Off:
1032*0a9764feSAndroid Build Coastguard Worker       a_args.active = false;
1033*0a9764feSAndroid Build Coastguard Worker       break;
1034*0a9764feSAndroid Build Coastguard Worker     case HWC2::PowerMode::On:
1035*0a9764feSAndroid Build Coastguard Worker       a_args.active = true;
1036*0a9764feSAndroid Build Coastguard Worker       break;
1037*0a9764feSAndroid Build Coastguard Worker     case HWC2::PowerMode::Doze:
1038*0a9764feSAndroid Build Coastguard Worker     case HWC2::PowerMode::DozeSuspend:
1039*0a9764feSAndroid Build Coastguard Worker       return HWC2::Error::Unsupported;
1040*0a9764feSAndroid Build Coastguard Worker     default:
1041*0a9764feSAndroid Build Coastguard Worker       ALOGE("Incorrect power mode value (%d)\n", mode_in);
1042*0a9764feSAndroid Build Coastguard Worker       return HWC2::Error::BadParameter;
1043*0a9764feSAndroid Build Coastguard Worker   }
1044*0a9764feSAndroid Build Coastguard Worker 
1045*0a9764feSAndroid Build Coastguard Worker   if (IsInHeadlessMode()) {
1046*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::None;
1047*0a9764feSAndroid Build Coastguard Worker   }
1048*0a9764feSAndroid Build Coastguard Worker 
1049*0a9764feSAndroid Build Coastguard Worker   if (a_args.active && *a_args.active) {
1050*0a9764feSAndroid Build Coastguard Worker     /*
1051*0a9764feSAndroid Build Coastguard Worker      * Setting the display to active before we have a composition
1052*0a9764feSAndroid Build Coastguard Worker      * can break some drivers, so skip setting a_args.active to
1053*0a9764feSAndroid Build Coastguard Worker      * true, as the next composition frame will implicitly activate
1054*0a9764feSAndroid Build Coastguard Worker      * the display
1055*0a9764feSAndroid Build Coastguard Worker      */
1056*0a9764feSAndroid Build Coastguard Worker     return GetPipe().atomic_state_manager->ActivateDisplayUsingDPMS() == 0
1057*0a9764feSAndroid Build Coastguard Worker                ? HWC2::Error::None
1058*0a9764feSAndroid Build Coastguard Worker                : HWC2::Error::BadParameter;
1059*0a9764feSAndroid Build Coastguard Worker   };
1060*0a9764feSAndroid Build Coastguard Worker 
1061*0a9764feSAndroid Build Coastguard Worker   auto err = GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args);
1062*0a9764feSAndroid Build Coastguard Worker   if (err) {
1063*0a9764feSAndroid Build Coastguard Worker     ALOGE("Failed to apply the dpms composition err=%d", err);
1064*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadParameter;
1065*0a9764feSAndroid Build Coastguard Worker   }
1066*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
1067*0a9764feSAndroid Build Coastguard Worker }
1068*0a9764feSAndroid Build Coastguard Worker 
SetVsyncEnabled(int32_t enabled)1069*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::SetVsyncEnabled(int32_t enabled) {
1070*0a9764feSAndroid Build Coastguard Worker   if (type_ == HWC2::DisplayType::Virtual) {
1071*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::None;
1072*0a9764feSAndroid Build Coastguard Worker   }
1073*0a9764feSAndroid Build Coastguard Worker 
1074*0a9764feSAndroid Build Coastguard Worker   vsync_event_en_ = HWC2_VSYNC_ENABLE == enabled;
1075*0a9764feSAndroid Build Coastguard Worker   if (vsync_event_en_) {
1076*0a9764feSAndroid Build Coastguard Worker     vsync_worker_->VSyncControl(true);
1077*0a9764feSAndroid Build Coastguard Worker   }
1078*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
1079*0a9764feSAndroid Build Coastguard Worker }
1080*0a9764feSAndroid Build Coastguard Worker 
ValidateDisplay(uint32_t * num_types,uint32_t * num_requests)1081*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::ValidateDisplay(uint32_t *num_types,
1082*0a9764feSAndroid Build Coastguard Worker                                         uint32_t *num_requests) {
1083*0a9764feSAndroid Build Coastguard Worker   if (IsInHeadlessMode()) {
1084*0a9764feSAndroid Build Coastguard Worker     *num_types = *num_requests = 0;
1085*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::None;
1086*0a9764feSAndroid Build Coastguard Worker   }
1087*0a9764feSAndroid Build Coastguard Worker 
1088*0a9764feSAndroid Build Coastguard Worker   /* In current drm_hwc design in case previous frame layer was not validated as
1089*0a9764feSAndroid Build Coastguard Worker    * a CLIENT, it is used by display controller (Front buffer). We have to store
1090*0a9764feSAndroid Build Coastguard Worker    * this state to provide the CLIENT with the release fences for such buffers.
1091*0a9764feSAndroid Build Coastguard Worker    */
1092*0a9764feSAndroid Build Coastguard Worker   for (auto &l : layers_) {
1093*0a9764feSAndroid Build Coastguard Worker     l.second.SetPriorBufferScanOutFlag(l.second.GetValidatedType() !=
1094*0a9764feSAndroid Build Coastguard Worker                                        HWC2::Composition::Client);
1095*0a9764feSAndroid Build Coastguard Worker   }
1096*0a9764feSAndroid Build Coastguard Worker 
1097*0a9764feSAndroid Build Coastguard Worker   return backend_->ValidateDisplay(this, num_types, num_requests);
1098*0a9764feSAndroid Build Coastguard Worker }
1099*0a9764feSAndroid Build Coastguard Worker 
GetOrderLayersByZPos()1100*0a9764feSAndroid Build Coastguard Worker std::vector<HwcLayer *> HwcDisplay::GetOrderLayersByZPos() {
1101*0a9764feSAndroid Build Coastguard Worker   std::vector<HwcLayer *> ordered_layers;
1102*0a9764feSAndroid Build Coastguard Worker   ordered_layers.reserve(layers_.size());
1103*0a9764feSAndroid Build Coastguard Worker 
1104*0a9764feSAndroid Build Coastguard Worker   for (auto &[handle, layer] : layers_) {
1105*0a9764feSAndroid Build Coastguard Worker     ordered_layers.emplace_back(&layer);
1106*0a9764feSAndroid Build Coastguard Worker   }
1107*0a9764feSAndroid Build Coastguard Worker 
1108*0a9764feSAndroid Build Coastguard Worker   std::sort(std::begin(ordered_layers), std::end(ordered_layers),
1109*0a9764feSAndroid Build Coastguard Worker             [](const HwcLayer *lhs, const HwcLayer *rhs) {
1110*0a9764feSAndroid Build Coastguard Worker               return lhs->GetZOrder() < rhs->GetZOrder();
1111*0a9764feSAndroid Build Coastguard Worker             });
1112*0a9764feSAndroid Build Coastguard Worker 
1113*0a9764feSAndroid Build Coastguard Worker   return ordered_layers;
1114*0a9764feSAndroid Build Coastguard Worker }
1115*0a9764feSAndroid Build Coastguard Worker 
GetDisplayVsyncPeriod(uint32_t * outVsyncPeriod)1116*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::GetDisplayVsyncPeriod(
1117*0a9764feSAndroid Build Coastguard Worker     uint32_t *outVsyncPeriod /* ns */) {
1118*0a9764feSAndroid Build Coastguard Worker   return GetDisplayAttribute(configs_.active_config_id,
1119*0a9764feSAndroid Build Coastguard Worker                              HWC2_ATTRIBUTE_VSYNC_PERIOD,
1120*0a9764feSAndroid Build Coastguard Worker                              (int32_t *)(outVsyncPeriod));
1121*0a9764feSAndroid Build Coastguard Worker }
1122*0a9764feSAndroid Build Coastguard Worker 
1123*0a9764feSAndroid Build Coastguard Worker #if __ANDROID_API__ > 29
GetDisplayConnectionType(uint32_t * outType)1124*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::GetDisplayConnectionType(uint32_t *outType) {
1125*0a9764feSAndroid Build Coastguard Worker   if (IsInHeadlessMode()) {
1126*0a9764feSAndroid Build Coastguard Worker     *outType = static_cast<uint32_t>(HWC2::DisplayConnectionType::Internal);
1127*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::None;
1128*0a9764feSAndroid Build Coastguard Worker   }
1129*0a9764feSAndroid Build Coastguard Worker   /* Primary display should be always internal,
1130*0a9764feSAndroid Build Coastguard Worker    * otherwise SF will be unhappy and will crash
1131*0a9764feSAndroid Build Coastguard Worker    */
1132*0a9764feSAndroid Build Coastguard Worker   if (GetPipe().connector->Get()->IsInternal() || handle_ == kPrimaryDisplay)
1133*0a9764feSAndroid Build Coastguard Worker     *outType = static_cast<uint32_t>(HWC2::DisplayConnectionType::Internal);
1134*0a9764feSAndroid Build Coastguard Worker   else if (GetPipe().connector->Get()->IsExternal())
1135*0a9764feSAndroid Build Coastguard Worker     *outType = static_cast<uint32_t>(HWC2::DisplayConnectionType::External);
1136*0a9764feSAndroid Build Coastguard Worker   else
1137*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadConfig;
1138*0a9764feSAndroid Build Coastguard Worker 
1139*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
1140*0a9764feSAndroid Build Coastguard Worker }
1141*0a9764feSAndroid Build Coastguard Worker 
SetActiveConfigWithConstraints(hwc2_config_t config,hwc_vsync_period_change_constraints_t * vsyncPeriodChangeConstraints,hwc_vsync_period_change_timeline_t * outTimeline)1142*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::SetActiveConfigWithConstraints(
1143*0a9764feSAndroid Build Coastguard Worker     hwc2_config_t config,
1144*0a9764feSAndroid Build Coastguard Worker     hwc_vsync_period_change_constraints_t *vsyncPeriodChangeConstraints,
1145*0a9764feSAndroid Build Coastguard Worker     hwc_vsync_period_change_timeline_t *outTimeline) {
1146*0a9764feSAndroid Build Coastguard Worker   if (type_ == HWC2::DisplayType::Virtual) {
1147*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::None;
1148*0a9764feSAndroid Build Coastguard Worker   }
1149*0a9764feSAndroid Build Coastguard Worker 
1150*0a9764feSAndroid Build Coastguard Worker   if (vsyncPeriodChangeConstraints == nullptr || outTimeline == nullptr) {
1151*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadParameter;
1152*0a9764feSAndroid Build Coastguard Worker   }
1153*0a9764feSAndroid Build Coastguard Worker 
1154*0a9764feSAndroid Build Coastguard Worker   uint32_t current_vsync_period{};
1155*0a9764feSAndroid Build Coastguard Worker   GetDisplayVsyncPeriod(&current_vsync_period);
1156*0a9764feSAndroid Build Coastguard Worker 
1157*0a9764feSAndroid Build Coastguard Worker   if (vsyncPeriodChangeConstraints->seamlessRequired) {
1158*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::SeamlessNotAllowed;
1159*0a9764feSAndroid Build Coastguard Worker   }
1160*0a9764feSAndroid Build Coastguard Worker 
1161*0a9764feSAndroid Build Coastguard Worker   outTimeline->refreshTimeNanos = vsyncPeriodChangeConstraints
1162*0a9764feSAndroid Build Coastguard Worker                                       ->desiredTimeNanos -
1163*0a9764feSAndroid Build Coastguard Worker                                   current_vsync_period;
1164*0a9764feSAndroid Build Coastguard Worker   auto ret = SetActiveConfigInternal(config, outTimeline->refreshTimeNanos);
1165*0a9764feSAndroid Build Coastguard Worker   if (ret != HWC2::Error::None) {
1166*0a9764feSAndroid Build Coastguard Worker     return ret;
1167*0a9764feSAndroid Build Coastguard Worker   }
1168*0a9764feSAndroid Build Coastguard Worker 
1169*0a9764feSAndroid Build Coastguard Worker   outTimeline->refreshRequired = true;
1170*0a9764feSAndroid Build Coastguard Worker   outTimeline->newVsyncAppliedTimeNanos = vsyncPeriodChangeConstraints
1171*0a9764feSAndroid Build Coastguard Worker                                               ->desiredTimeNanos;
1172*0a9764feSAndroid Build Coastguard Worker 
1173*0a9764feSAndroid Build Coastguard Worker   last_vsync_ts_ = 0;
1174*0a9764feSAndroid Build Coastguard Worker   vsync_tracking_en_ = true;
1175*0a9764feSAndroid Build Coastguard Worker   vsync_worker_->VSyncControl(true);
1176*0a9764feSAndroid Build Coastguard Worker 
1177*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
1178*0a9764feSAndroid Build Coastguard Worker }
1179*0a9764feSAndroid Build Coastguard Worker 
SetAutoLowLatencyMode(bool)1180*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::SetAutoLowLatencyMode(bool /*on*/) {
1181*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::Unsupported;
1182*0a9764feSAndroid Build Coastguard Worker }
1183*0a9764feSAndroid Build Coastguard Worker 
GetSupportedContentTypes(uint32_t * outNumSupportedContentTypes,const uint32_t * outSupportedContentTypes)1184*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::GetSupportedContentTypes(
1185*0a9764feSAndroid Build Coastguard Worker     uint32_t *outNumSupportedContentTypes,
1186*0a9764feSAndroid Build Coastguard Worker     const uint32_t *outSupportedContentTypes) {
1187*0a9764feSAndroid Build Coastguard Worker   if (outSupportedContentTypes == nullptr)
1188*0a9764feSAndroid Build Coastguard Worker     *outNumSupportedContentTypes = 0;
1189*0a9764feSAndroid Build Coastguard Worker 
1190*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
1191*0a9764feSAndroid Build Coastguard Worker }
1192*0a9764feSAndroid Build Coastguard Worker 
SetContentType(int32_t contentType)1193*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::SetContentType(int32_t contentType) {
1194*0a9764feSAndroid Build Coastguard Worker   /* Maps exactly to the content_type DRM connector property:
1195*0a9764feSAndroid Build Coastguard Worker    * https://elixir.bootlin.com/linux/v6.11/source/include/uapi/drm/drm_mode.h#L107
1196*0a9764feSAndroid Build Coastguard Worker    */
1197*0a9764feSAndroid Build Coastguard Worker   if (contentType < HWC2_CONTENT_TYPE_NONE || contentType > HWC2_CONTENT_TYPE_GAME)
1198*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadParameter;
1199*0a9764feSAndroid Build Coastguard Worker 
1200*0a9764feSAndroid Build Coastguard Worker   content_type_ = contentType;
1201*0a9764feSAndroid Build Coastguard Worker 
1202*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
1203*0a9764feSAndroid Build Coastguard Worker }
1204*0a9764feSAndroid Build Coastguard Worker #endif
1205*0a9764feSAndroid Build Coastguard Worker 
1206*0a9764feSAndroid Build Coastguard Worker #if __ANDROID_API__ > 28
GetDisplayIdentificationData(uint8_t * outPort,uint32_t * outDataSize,uint8_t * outData)1207*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::GetDisplayIdentificationData(uint8_t *outPort,
1208*0a9764feSAndroid Build Coastguard Worker                                                      uint32_t *outDataSize,
1209*0a9764feSAndroid Build Coastguard Worker                                                      uint8_t *outData) {
1210*0a9764feSAndroid Build Coastguard Worker   if (IsInHeadlessMode()) {
1211*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::Unsupported;
1212*0a9764feSAndroid Build Coastguard Worker   }
1213*0a9764feSAndroid Build Coastguard Worker 
1214*0a9764feSAndroid Build Coastguard Worker   auto blob = GetPipe().connector->Get()->GetEdidBlob();
1215*0a9764feSAndroid Build Coastguard Worker   if (!blob) {
1216*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::Unsupported;
1217*0a9764feSAndroid Build Coastguard Worker   }
1218*0a9764feSAndroid Build Coastguard Worker 
1219*0a9764feSAndroid Build Coastguard Worker   *outPort = handle_; /* TDOD(nobody): What should be here? */
1220*0a9764feSAndroid Build Coastguard Worker 
1221*0a9764feSAndroid Build Coastguard Worker   if (outData) {
1222*0a9764feSAndroid Build Coastguard Worker     *outDataSize = std::min(*outDataSize, blob->length);
1223*0a9764feSAndroid Build Coastguard Worker     memcpy(outData, blob->data, *outDataSize);
1224*0a9764feSAndroid Build Coastguard Worker   } else {
1225*0a9764feSAndroid Build Coastguard Worker     *outDataSize = blob->length;
1226*0a9764feSAndroid Build Coastguard Worker   }
1227*0a9764feSAndroid Build Coastguard Worker 
1228*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
1229*0a9764feSAndroid Build Coastguard Worker }
1230*0a9764feSAndroid Build Coastguard Worker 
GetDisplayCapabilities(uint32_t * outNumCapabilities,uint32_t * outCapabilities)1231*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::GetDisplayCapabilities(uint32_t *outNumCapabilities,
1232*0a9764feSAndroid Build Coastguard Worker                                                uint32_t *outCapabilities) {
1233*0a9764feSAndroid Build Coastguard Worker   if (outNumCapabilities == nullptr) {
1234*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadParameter;
1235*0a9764feSAndroid Build Coastguard Worker   }
1236*0a9764feSAndroid Build Coastguard Worker 
1237*0a9764feSAndroid Build Coastguard Worker   bool skip_ctm = false;
1238*0a9764feSAndroid Build Coastguard Worker 
1239*0a9764feSAndroid Build Coastguard Worker   // Skip client CTM if user requested DRM_OR_IGNORE
1240*0a9764feSAndroid Build Coastguard Worker   if (GetHwc()->GetResMan().GetCtmHandling() == CtmHandling::kDrmOrIgnore)
1241*0a9764feSAndroid Build Coastguard Worker     skip_ctm = true;
1242*0a9764feSAndroid Build Coastguard Worker 
1243*0a9764feSAndroid Build Coastguard Worker   // Skip client CTM if DRM can handle it
1244*0a9764feSAndroid Build Coastguard Worker   if (!skip_ctm && !IsInHeadlessMode() &&
1245*0a9764feSAndroid Build Coastguard Worker       GetPipe().crtc->Get()->GetCtmProperty())
1246*0a9764feSAndroid Build Coastguard Worker     skip_ctm = true;
1247*0a9764feSAndroid Build Coastguard Worker 
1248*0a9764feSAndroid Build Coastguard Worker   if (!skip_ctm) {
1249*0a9764feSAndroid Build Coastguard Worker     *outNumCapabilities = 0;
1250*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::None;
1251*0a9764feSAndroid Build Coastguard Worker   }
1252*0a9764feSAndroid Build Coastguard Worker 
1253*0a9764feSAndroid Build Coastguard Worker   *outNumCapabilities = 1;
1254*0a9764feSAndroid Build Coastguard Worker   if (outCapabilities) {
1255*0a9764feSAndroid Build Coastguard Worker     outCapabilities[0] = HWC2_DISPLAY_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
1256*0a9764feSAndroid Build Coastguard Worker   }
1257*0a9764feSAndroid Build Coastguard Worker 
1258*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
1259*0a9764feSAndroid Build Coastguard Worker }
1260*0a9764feSAndroid Build Coastguard Worker 
GetDisplayBrightnessSupport(bool * supported)1261*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::GetDisplayBrightnessSupport(bool *supported) {
1262*0a9764feSAndroid Build Coastguard Worker   *supported = false;
1263*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
1264*0a9764feSAndroid Build Coastguard Worker }
1265*0a9764feSAndroid Build Coastguard Worker 
SetDisplayBrightness(float)1266*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::SetDisplayBrightness(float /* brightness */) {
1267*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::Unsupported;
1268*0a9764feSAndroid Build Coastguard Worker }
1269*0a9764feSAndroid Build Coastguard Worker 
1270*0a9764feSAndroid Build Coastguard Worker #endif /* __ANDROID_API__ > 28 */
1271*0a9764feSAndroid Build Coastguard Worker 
1272*0a9764feSAndroid Build Coastguard Worker #if __ANDROID_API__ > 27
1273*0a9764feSAndroid Build Coastguard Worker 
GetRenderIntents(int32_t mode,uint32_t * outNumIntents,int32_t * outIntents)1274*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::GetRenderIntents(
1275*0a9764feSAndroid Build Coastguard Worker     int32_t mode, uint32_t *outNumIntents,
1276*0a9764feSAndroid Build Coastguard Worker     int32_t * /*android_render_intent_v1_1_t*/ outIntents) {
1277*0a9764feSAndroid Build Coastguard Worker   if (mode != HAL_COLOR_MODE_NATIVE) {
1278*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadParameter;
1279*0a9764feSAndroid Build Coastguard Worker   }
1280*0a9764feSAndroid Build Coastguard Worker 
1281*0a9764feSAndroid Build Coastguard Worker   if (outIntents == nullptr) {
1282*0a9764feSAndroid Build Coastguard Worker     *outNumIntents = 1;
1283*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::None;
1284*0a9764feSAndroid Build Coastguard Worker   }
1285*0a9764feSAndroid Build Coastguard Worker   *outNumIntents = 1;
1286*0a9764feSAndroid Build Coastguard Worker   outIntents[0] = HAL_RENDER_INTENT_COLORIMETRIC;
1287*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
1288*0a9764feSAndroid Build Coastguard Worker }
1289*0a9764feSAndroid Build Coastguard Worker 
SetColorModeWithIntent(int32_t mode,int32_t intent)1290*0a9764feSAndroid Build Coastguard Worker HWC2::Error HwcDisplay::SetColorModeWithIntent(int32_t mode, int32_t intent) {
1291*0a9764feSAndroid Build Coastguard Worker   if (intent < HAL_RENDER_INTENT_COLORIMETRIC ||
1292*0a9764feSAndroid Build Coastguard Worker       intent > HAL_RENDER_INTENT_TONE_MAP_ENHANCE)
1293*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::BadParameter;
1294*0a9764feSAndroid Build Coastguard Worker 
1295*0a9764feSAndroid Build Coastguard Worker   if (intent != HAL_RENDER_INTENT_COLORIMETRIC)
1296*0a9764feSAndroid Build Coastguard Worker     return HWC2::Error::Unsupported;
1297*0a9764feSAndroid Build Coastguard Worker 
1298*0a9764feSAndroid Build Coastguard Worker   auto err = SetColorMode(mode);
1299*0a9764feSAndroid Build Coastguard Worker   if (err != HWC2::Error::None) return err;
1300*0a9764feSAndroid Build Coastguard Worker 
1301*0a9764feSAndroid Build Coastguard Worker   return HWC2::Error::None;
1302*0a9764feSAndroid Build Coastguard Worker }
1303*0a9764feSAndroid Build Coastguard Worker 
1304*0a9764feSAndroid Build Coastguard Worker #endif /* __ANDROID_API__ > 27 */
1305*0a9764feSAndroid Build Coastguard Worker 
backend() const1306*0a9764feSAndroid Build Coastguard Worker const Backend *HwcDisplay::backend() const {
1307*0a9764feSAndroid Build Coastguard Worker   return backend_.get();
1308*0a9764feSAndroid Build Coastguard Worker }
1309*0a9764feSAndroid Build Coastguard Worker 
set_backend(std::unique_ptr<Backend> backend)1310*0a9764feSAndroid Build Coastguard Worker void HwcDisplay::set_backend(std::unique_ptr<Backend> backend) {
1311*0a9764feSAndroid Build Coastguard Worker   backend_ = std::move(backend);
1312*0a9764feSAndroid Build Coastguard Worker }
1313*0a9764feSAndroid Build Coastguard Worker 
1314*0a9764feSAndroid Build Coastguard Worker }  // namespace android
1315