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(¤t_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