blob: 628c0f0bcb1705e1d5af7e2b213149b5b8a0a2bf [file] [log] [blame]
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001/*
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05302 * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved.
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05003 * Not a Contribution.
4 *
5 * Copyright 2015 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070020#include <cutils/properties.h>
Naseer Ahmedb92e73f2016-03-12 02:03:48 -050021#include <errno.h>
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070022#include <math.h>
23#include <sync/sync.h>
Naseer Ahmed065cff72017-03-20 15:07:28 -040024#include <sys/types.h>
25#include <sys/stat.h>
Naseer Ahmedb92e73f2016-03-12 02:03:48 -050026#include <utils/constants.h>
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070027#include <utils/debug.h>
Rajavenu Kyatham9d509582019-02-13 15:29:55 +053028#include <utils/utils.h>
Naseer Ahmedb92e73f2016-03-12 02:03:48 -050029#include <utils/formats.h>
30#include <utils/rect.h>
Saurabh Shah7d476ed2016-06-27 16:40:58 -070031#include <qd_utils.h>
Naseer Ahmed8584a0f2020-02-19 22:23:30 -050032#include <vendor/qti/hardware/display/composer/3.0/IQtiComposerClient.h>
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070033
34#include <algorithm>
Naseer Ahmed913502b2017-04-18 16:05:05 -040035#include <iomanip>
Naseer Ahmedb92e73f2016-03-12 02:03:48 -050036#include <map>
Naseer Ahmed1fd59ea2016-05-05 13:59:23 -040037#include <sstream>
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070038#include <string>
Naseer Ahmedb92e73f2016-03-12 02:03:48 -050039#include <utility>
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070040#include <vector>
Naseer Ahmedb92e73f2016-03-12 02:03:48 -050041
42#include "hwc_display.h"
43#include "hwc_debugger.h"
Arun Kumar K.R51be3d12017-03-31 19:54:38 -070044#include "hwc_tonemapper.h"
Saurabh Shah864304d2017-09-13 14:39:30 -070045#include "hwc_session.h"
Arun Kumar K.R51be3d12017-03-31 19:54:38 -070046
Naseer Ahmedb92e73f2016-03-12 02:03:48 -050047#ifdef QTI_BSP
48#include <hardware/display_defs.h>
49#endif
50
51#define __CLASS__ "HWCDisplay"
52
53namespace sdm {
54
Mahesh Aiaf3a1f992019-01-16 13:07:42 -080055uint32_t HWCDisplay::throttling_refresh_rate_ = 60;
Sushil Chauhandbd8db42020-02-28 13:07:48 -080056constexpr uint32_t kVsyncTimeDriftNs = 1000000;
Mahesh Aiaf3a1f992019-01-16 13:07:42 -080057
Arun Kumar K.R2a419be2018-04-27 12:43:58 +053058bool NeedsToneMap(const LayerStack &layer_stack) {
59 for (Layer *layer : layer_stack.layers) {
60 if (layer->request.flags.tone_map) {
61 return true;
62 }
63 }
64 return false;
65}
66
Sushil Chauhandbd8db42020-02-28 13:07:48 -080067bool IsTimeAfterOrEqualVsyncTime(int64_t time, int64_t vsync_time) {
68 return ((vsync_time != INT64_MAX) && ((time - (vsync_time - kVsyncTimeDriftNs)) >= 0));
69}
70
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070071HWCColorMode::HWCColorMode(DisplayInterface *display_intf) : display_intf_(display_intf) {}
72
73HWC2::Error HWCColorMode::Init() {
74 PopulateColorModes();
Qing Huang97b35442019-04-30 13:51:17 -070075 return HWC2::Error::None;
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070076}
77
78HWC2::Error HWCColorMode::DeInit() {
Naseer Ahmede7a77982018-06-04 10:56:04 -040079 color_mode_map_.clear();
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070080 return HWC2::Error::None;
81}
82
83uint32_t HWCColorMode::GetColorModeCount() {
Naseer Ahmede7a77982018-06-04 10:56:04 -040084 uint32_t count = UINT32(color_mode_map_.size());
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070085 DLOGI("Supported color mode count = %d", count);
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070086 return std::max(1U, count);
87}
88
Naseer Ahmede7a77982018-06-04 10:56:04 -040089uint32_t HWCColorMode::GetRenderIntentCount(ColorMode mode) {
90 uint32_t count = UINT32(color_mode_map_[mode].size());
91 DLOGI("mode: %d supported rendering intent count = %d", mode, count);
92 return std::max(1U, count);
93}
94
95HWC2::Error HWCColorMode::GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes) {
96 auto it = color_mode_map_.begin();
97 *out_num_modes = std::min(*out_num_modes, UINT32(color_mode_map_.size()));
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +053098 for (uint32_t i = 0; i < *out_num_modes; it++, i++) {
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070099 out_modes[i] = it->first;
Naseer Ahmede7a77982018-06-04 10:56:04 -0400100 DLOGI("Color mode = %d is supported", out_modes[i]);
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700101 }
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700102 return HWC2::Error::None;
103}
104
Naseer Ahmede7a77982018-06-04 10:56:04 -0400105HWC2::Error HWCColorMode::GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
106 RenderIntent *out_intents) {
107 if (color_mode_map_.find(mode) == color_mode_map_.end()) {
108 return HWC2::Error::BadParameter;
109 }
110 auto it = color_mode_map_[mode].begin();
111 *out_num_intents = std::min(*out_num_intents, UINT32(color_mode_map_[mode].size()));
112 for (uint32_t i = 0; i < *out_num_intents; it++, i++) {
113 out_intents[i] = it->first;
114 DLOGI("Color mode = %d is supported with render intent = %d", mode, out_intents[i]);
115 }
116 return HWC2::Error::None;
117}
118
Sushil Chauhan8008d602018-09-04 14:43:27 -0700119HWC2::Error HWCColorMode::ValidateColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
Gousemoodhin Nadaf0e566872019-05-13 16:14:54 +0530120 if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_BT2020) {
Xu Yang47f44092019-02-13 14:09:53 +0800121 DLOGE("Invalid mode: %d", mode);
Naseer Ahmed7cb8f7a2017-05-12 16:33:57 -0400122 return HWC2::Error::BadParameter;
123 }
Naseer Ahmede7a77982018-06-04 10:56:04 -0400124 if (color_mode_map_.find(mode) == color_mode_map_.end()) {
Xu Yang47f44092019-02-13 14:09:53 +0800125 DLOGE("Could not find mode: %d", mode);
Naseer Ahmede7a77982018-06-04 10:56:04 -0400126 return HWC2::Error::Unsupported;
127 }
128 if (color_mode_map_[mode].find(intent) == color_mode_map_[mode].end()) {
Xu Yang47f44092019-02-13 14:09:53 +0800129 DLOGE("Could not find render intent %d in mode %d", intent, mode);
Arun Kumar K.R1018d5b2017-06-08 13:51:05 +0530130 return HWC2::Error::Unsupported;
131 }
132
Sushil Chauhan8008d602018-09-04 14:43:27 -0700133 return HWC2::Error::None;
134}
135
136HWC2::Error HWCColorMode::SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
137 DTRACE_SCOPED();
138 HWC2::Error hwc_error = ValidateColorModeWithRenderIntent(mode, intent);
139 if (hwc_error != HWC2::Error::None) {
140 return hwc_error;
141 }
142
143 if (current_color_mode_ == mode && current_render_intent_ == intent) {
144 return HWC2::Error::None;
145 }
146
Xu Yang84e61412018-12-06 14:52:16 +0800147 auto mode_string = color_mode_map_[mode][intent][kSdrType];
Sushil Chauhan8008d602018-09-04 14:43:27 -0700148 DisplayError error = display_intf_->SetColorMode(mode_string);
149 if (error != kErrorNone) {
150 DLOGE("failed for mode = %d intent = %d name = %s", mode, intent, mode_string.c_str());
151 return HWC2::Error::Unsupported;
152 }
153 // The mode does not have the PCC configured, restore the transform
154 RestoreColorTransform();
155
156 current_color_mode_ = mode;
157 current_render_intent_ = intent;
158 DLOGV_IF(kTagClient, "Successfully applied mode = %d intent = %d name = %s", mode, intent,
159 mode_string.c_str());
160 return HWC2::Error::None;
161}
162
163HWC2::Error HWCColorMode::CacheColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
164 HWC2::Error error = ValidateColorModeWithRenderIntent(mode, intent);
165 if (error != HWC2::Error::None) {
166 return error;
167 }
168
Naseer Ahmed6f8fefb2018-06-04 10:56:04 -0400169 if (current_color_mode_ == mode && current_render_intent_ == intent) {
170 return HWC2::Error::None;
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700171 }
172
Naseer Ahmede7a77982018-06-04 10:56:04 -0400173 current_color_mode_ = mode;
174 current_render_intent_ = intent;
Sushil Chauhan7cd110d2018-08-24 17:17:55 -0700175 apply_mode_ = true;
176
177 return HWC2::Error::None;
178}
179
Padmanabhan Komanduru9a6b1202020-03-24 20:38:33 +0530180void HWCColorMode::SetApplyMode(bool enable) {
181 apply_mode_ = enable;
182}
183
Xu Yang84e61412018-12-06 14:52:16 +0800184HWC2::Error HWCColorMode::ApplyCurrentColorModeWithRenderIntent(bool hdr_present) {
Gousemoodhin Nadaf3adacfb2019-05-31 16:06:13 +0530185 // If panel does not support color modes, do not set color mode.
186 if (color_mode_map_.size() <= 1) {
187 return HWC2::Error::None;
188 }
Sushil Chauhan7cd110d2018-08-24 17:17:55 -0700189 if (!apply_mode_) {
Xu Yang84e61412018-12-06 14:52:16 +0800190 if ((hdr_present && curr_dynamic_range_ == kHdrType) ||
191 (!hdr_present && curr_dynamic_range_ == kSdrType))
192 return HWC2::Error::None;
Sushil Chauhan7cd110d2018-08-24 17:17:55 -0700193 }
194
195 apply_mode_ = false;
Xu Yang84e61412018-12-06 14:52:16 +0800196 curr_dynamic_range_ = (hdr_present)? kHdrType : kSdrType;
197
198 // select mode according to the blend space and dynamic range
199 std::string mode_string = preferred_mode_[current_color_mode_][curr_dynamic_range_];
200 if (mode_string.empty()) {
201 mode_string = color_mode_map_[current_color_mode_][current_render_intent_][curr_dynamic_range_];
Naseer Ahmed1d092ea2019-05-01 20:34:52 -0400202 if (mode_string.empty() && hdr_present) {
203 // Use the colorimetric HDR mode, if an HDR mode with the current render intent is not present
204 mode_string = color_mode_map_[current_color_mode_][RenderIntent::COLORIMETRIC][kHdrType];
205 }
Xu Yang84e61412018-12-06 14:52:16 +0800206 if (mode_string.empty() &&
Gousemoodhin Nadafd21743d2019-07-18 14:42:54 +0530207 (current_color_mode_ == ColorMode::DISPLAY_P3 ||
208 current_color_mode_ == ColorMode::DISPLAY_BT2020) &&
209 curr_dynamic_range_ == kHdrType) {
210 // fall back to display_p3/display_bt2020 SDR mode if there is no HDR mode
Xu Yang84e61412018-12-06 14:52:16 +0800211 mode_string = color_mode_map_[current_color_mode_][current_render_intent_][kSdrType];
212 }
Sushil Chauhan7cd110d2018-08-24 17:17:55 -0700213 }
214
Xu Yang84e61412018-12-06 14:52:16 +0800215 auto error = SetPreferredColorModeInternal(mode_string, false, NULL, NULL);
216 if (error == HWC2::Error::None) {
217 // The mode does not have the PCC configured, restore the transform
218 RestoreColorTransform();
219 DLOGV_IF(kTagClient, "Successfully applied mode = %d intent = %d range = %d name = %s",
220 current_color_mode_, current_render_intent_, curr_dynamic_range_, mode_string.c_str());
221 }
Sushil Chauhan7cd110d2018-08-24 17:17:55 -0700222
Xu Yang84e61412018-12-06 14:52:16 +0800223 return error;
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700224}
225
Naseer Ahmed6776dae2017-05-09 11:49:41 -0400226HWC2::Error HWCColorMode::SetColorModeById(int32_t color_mode_id) {
227 DLOGI("Applying mode: %d", color_mode_id);
228 DisplayError error = display_intf_->SetColorModeById(color_mode_id);
229 if (error != kErrorNone) {
Saurabh Dubeyd90a6a42017-10-24 16:28:01 +0530230 DLOGI_IF(kTagClient, "Failed to apply mode: %d", color_mode_id);
Naseer Ahmed6776dae2017-05-09 11:49:41 -0400231 return HWC2::Error::BadParameter;
232 }
233 return HWC2::Error::None;
234}
235
Xu Yang84e61412018-12-06 14:52:16 +0800236HWC2::Error HWCColorMode::SetPreferredColorModeInternal(const std::string &mode_string,
237 bool from_client, ColorMode *color_mode, DynamicRangeType *dynamic_range) {
238 DisplayError error = kErrorNone;
239 ColorMode mode = ColorMode::NATIVE;
240 DynamicRangeType range = kSdrType;
241
242 if (from_client) {
243 // get blend space and dynamic range of the mode
244 AttrVal attr;
245 std::string color_gamut_string, dynamic_range_string;
246 error = display_intf_->GetColorModeAttr(mode_string, &attr);
247 if (error) {
Pullakavi Srinivasce3692b2020-02-13 01:14:09 +0530248 DLOGE("Failed to get mode attributes for mode %s", mode_string.c_str());
Xu Yang84e61412018-12-06 14:52:16 +0800249 return HWC2::Error::BadParameter;
250 }
251
252 if (!attr.empty()) {
253 for (auto &it : attr) {
254 if (it.first.find(kColorGamutAttribute) != std::string::npos) {
255 color_gamut_string = it.second;
256 } else if (it.first.find(kDynamicRangeAttribute) != std::string::npos) {
257 dynamic_range_string = it.second;
258 }
259 }
260 }
261
262 if (color_gamut_string.empty() || dynamic_range_string.empty()) {
263 DLOGE("Invalid attributes for mode %s: color_gamut = %s, dynamic_range = %s",
264 mode_string.c_str(), color_gamut_string.c_str(), dynamic_range_string.c_str());
265 return HWC2::Error::BadParameter;
266 }
267
268 if (color_gamut_string == kDcip3) {
269 mode = ColorMode::DISPLAY_P3;
270 } else if (color_gamut_string == kSrgb) {
271 mode = ColorMode::SRGB;
272 }
273 if (dynamic_range_string == kHdr) {
274 range = kHdrType;
275 }
276
277 if (color_mode) {
278 *color_mode = mode;
279 }
280 if (dynamic_range) {
281 *dynamic_range = range;
282 }
283 }
284
285 // apply the mode from client if it matches
286 // the current blend space and dynamic range,
287 // skip the check for the mode from SF.
288 if ((!from_client) || (current_color_mode_ == mode && curr_dynamic_range_ == range)) {
289 DLOGI("Applying mode: %s", mode_string.c_str());
290 error = display_intf_->SetColorMode(mode_string);
291 if (error != kErrorNone) {
292 DLOGE("Failed to apply mode: %s", mode_string.c_str());
293 return HWC2::Error::BadParameter;
294 }
295 }
296
297 return HWC2::Error::None;
298}
299
300HWC2::Error HWCColorMode::SetColorModeFromClientApi(std::string mode_string) {
301 ColorMode mode = ColorMode::NATIVE;
302 DynamicRangeType range = kSdrType;
303
304 auto error = SetPreferredColorModeInternal(mode_string, true, &mode, &range);
305 if (error == HWC2::Error::None) {
306 preferred_mode_[mode][range] = mode_string;
307 DLOGV_IF(kTagClient, "Put mode %s(mode %d, range %d) into preferred_mode",
308 mode_string.c_str(), mode, range);
309 }
310
311 return error;
312}
313
Ch Ganesh Kumar5d43ff62017-10-13 19:01:47 +0530314HWC2::Error HWCColorMode::RestoreColorTransform() {
315 DisplayError error = display_intf_->SetColorTransform(kColorTransformMatrixCount, color_matrix_);
316 if (error != kErrorNone) {
317 DLOGE("Failed to set Color Transform");
318 return HWC2::Error::BadParameter;
319 }
320
321 return HWC2::Error::None;
322}
323
Naseer Ahmede7a77982018-06-04 10:56:04 -0400324HWC2::Error HWCColorMode::SetColorTransform(const float *matrix,
325 android_color_transform_t /*hint*/) {
Naseer Ahmedf5187022017-07-24 16:15:28 -0400326 DTRACE_SCOPED();
Naseer Ahmede7a77982018-06-04 10:56:04 -0400327 auto status = HWC2::Error::None;
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700328 double color_matrix[kColorTransformMatrixCount] = {0};
329 CopyColorTransformMatrix(matrix, color_matrix);
330
Naseer Ahmede7a77982018-06-04 10:56:04 -0400331 DisplayError error = display_intf_->SetColorTransform(kColorTransformMatrixCount, color_matrix);
332 if (error != kErrorNone) {
333 DLOGE("Failed to set Color Transform Matrix");
334 status = HWC2::Error::Unsupported;
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700335 }
Naseer Ahmede7a77982018-06-04 10:56:04 -0400336 CopyColorTransformMatrix(matrix, color_matrix_);
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700337 return status;
338}
339
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700340void HWCColorMode::PopulateColorModes() {
341 uint32_t color_mode_count = 0;
Naseer Ahmede7a77982018-06-04 10:56:04 -0400342 // SDM returns modes which have attributes defining mode and rendering intent
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700343 DisplayError error = display_intf_->GetColorModeCount(&color_mode_count);
344 if (error != kErrorNone || (color_mode_count == 0)) {
345 DLOGW("GetColorModeCount failed, use native color mode");
Xu Yang84e61412018-12-06 14:52:16 +0800346 color_mode_map_[ColorMode::NATIVE][RenderIntent::COLORIMETRIC]
347 [kSdrType] = "hal_native_identity";
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700348 return;
349 }
350
Saurabh Dubeyd90a6a42017-10-24 16:28:01 +0530351 DLOGV_IF(kTagClient, "Color Modes supported count = %d", color_mode_count);
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700352
353 std::vector<std::string> color_modes(color_mode_count);
354 error = display_intf_->GetColorModes(&color_mode_count, &color_modes);
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700355 for (uint32_t i = 0; i < color_mode_count; i++) {
356 std::string &mode_string = color_modes.at(i);
Saurabh Dubeyd90a6a42017-10-24 16:28:01 +0530357 DLOGV_IF(kTagClient, "Color Mode[%d] = %s", i, mode_string.c_str());
Qing Huang3f21afb2017-04-19 15:11:49 +0800358 AttrVal attr;
359 error = display_intf_->GetColorModeAttr(mode_string, &attr);
Gousemoodhin Nadaf56186602018-06-03 15:23:10 +0530360 std::string color_gamut = kNative, dynamic_range = kSdr, pic_quality = kStandard, transfer;
Xu Yang47f44092019-02-13 14:09:53 +0800361 int int_render_intent = -1;
Qing Huang3f21afb2017-04-19 15:11:49 +0800362 if (!attr.empty()) {
Qing Huang3f21afb2017-04-19 15:11:49 +0800363 for (auto &it : attr) {
364 if (it.first.find(kColorGamutAttribute) != std::string::npos) {
365 color_gamut = it.second;
366 } else if (it.first.find(kDynamicRangeAttribute) != std::string::npos) {
367 dynamic_range = it.second;
368 } else if (it.first.find(kPictureQualityAttribute) != std::string::npos) {
369 pic_quality = it.second;
Gousemoodhin Nadaf56186602018-06-03 15:23:10 +0530370 } else if (it.first.find(kGammaTransferAttribute) != std::string::npos) {
371 transfer = it.second;
Xu Yang47f44092019-02-13 14:09:53 +0800372 } else if (it.first.find(kRenderIntentAttribute) != std::string::npos) {
373 int_render_intent = std::stoi(it.second);
Qing Huang3f21afb2017-04-19 15:11:49 +0800374 }
375 }
Saurabh Dubeyd90a6a42017-10-24 16:28:01 +0530376
Xu Yang47f44092019-02-13 14:09:53 +0800377 if (int_render_intent < 0 || int_render_intent > MAX_EXTENDED_RENDER_INTENT) {
378 DLOGW("Invalid render intent %d for mode %s", int_render_intent, mode_string.c_str());
379 continue;
380 }
381 DLOGV_IF(kTagClient, "color_gamut : %s, dynamic_range : %s, pic_quality : %s, "
382 "render_intent : %d", color_gamut.c_str(), dynamic_range.c_str(),
383 pic_quality.c_str(), int_render_intent);
384
385 auto render_intent = static_cast<RenderIntent>(int_render_intent);
Naseer Ahmede7a77982018-06-04 10:56:04 -0400386 if (color_gamut == kNative) {
Xu Yang47f44092019-02-13 14:09:53 +0800387 color_mode_map_[ColorMode::NATIVE][render_intent][kSdrType] = mode_string;
Qing Huang3f21afb2017-04-19 15:11:49 +0800388 }
Naseer Ahmed0c689d42017-05-15 17:14:48 -0400389
Naseer Ahmede7a77982018-06-04 10:56:04 -0400390 if (color_gamut == kSrgb && dynamic_range == kSdr) {
Xu Yang47f44092019-02-13 14:09:53 +0800391 color_mode_map_[ColorMode::SRGB][render_intent][kSdrType] = mode_string;
Naseer Ahmede7a77982018-06-04 10:56:04 -0400392 }
393
394 if (color_gamut == kDcip3 && dynamic_range == kSdr) {
Xu Yang47f44092019-02-13 14:09:53 +0800395 color_mode_map_[ColorMode::DISPLAY_P3][render_intent][kSdrType] = mode_string;
Naseer Ahmede7a77982018-06-04 10:56:04 -0400396 }
Xu Yang47f44092019-02-13 14:09:53 +0800397 if (color_gamut == kDcip3 && dynamic_range == kHdr) {
Xu Yang84e61412018-12-06 14:52:16 +0800398 if (display_intf_->IsSupportSsppTonemap()) {
Xu Yang47f44092019-02-13 14:09:53 +0800399 color_mode_map_[ColorMode::DISPLAY_P3][render_intent][kHdrType] = mode_string;
400 } else if (pic_quality == kStandard) {
Qing Huang6d31af62019-08-12 13:42:41 +0800401 color_mode_map_[ColorMode::BT2100_PQ][render_intent]
Xu Yang84e61412018-12-06 14:52:16 +0800402 [kHdrType] = mode_string;
Qing Huang6d31af62019-08-12 13:42:41 +0800403 color_mode_map_[ColorMode::BT2100_HLG][render_intent]
Xu Yang84e61412018-12-06 14:52:16 +0800404 [kHdrType] = mode_string;
405 }
Gousemoodhin Nadaf56186602018-06-03 15:23:10 +0530406 } else if (color_gamut == kBt2020) {
407 if (transfer == kSt2084) {
Xu Yang84e61412018-12-06 14:52:16 +0800408 color_mode_map_[ColorMode::BT2100_PQ][RenderIntent::COLORIMETRIC]
409 [kHdrType] = mode_string;
Gousemoodhin Nadaf56186602018-06-03 15:23:10 +0530410 } else if (transfer == kHlg) {
Xu Yang84e61412018-12-06 14:52:16 +0800411 color_mode_map_[ColorMode::BT2100_HLG][RenderIntent::COLORIMETRIC]
412 [kHdrType] = mode_string;
Gousemoodhin Nadaf0e566872019-05-13 16:14:54 +0530413 } else if (transfer == kSrgb) {
414 color_mode_map_[ColorMode::DISPLAY_BT2020][RenderIntent::COLORIMETRIC]
415 [kSdrType] = mode_string;
Gousemoodhin Nadaf56186602018-06-03 15:23:10 +0530416 }
Naseer Ahmede7a77982018-06-04 10:56:04 -0400417 }
418 } else {
419 // Look at the mode names, if no attributes are found
Qing Huang3f21afb2017-04-19 15:11:49 +0800420 if (mode_string.find("hal_native") != std::string::npos) {
Xu Yang84e61412018-12-06 14:52:16 +0800421 color_mode_map_[ColorMode::NATIVE][RenderIntent::COLORIMETRIC]
422 [kSdrType] = mode_string;
Qing Huang3f21afb2017-04-19 15:11:49 +0800423 }
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700424 }
425 }
426}
427
Naseer Ahmed913502b2017-04-18 16:05:05 -0400428void HWCColorMode::Dump(std::ostringstream* os) {
Naseer Ahmede7a77982018-06-04 10:56:04 -0400429 *os << "color modes supported: \n";
430 for (auto it : color_mode_map_) {
431 *os << "mode: " << static_cast<int32_t>(it.first) << " RIs { ";
Xu Yang84e61412018-12-06 14:52:16 +0800432 for (auto render_intent_it : color_mode_map_[it.first]) {
433 *os << static_cast<int32_t>(render_intent_it.first) << " dynamic_range [ ";
434 for (auto range_it : color_mode_map_[it.first][render_intent_it.first]) {
435 *os << static_cast<int32_t>(range_it.first) << " ";
436 }
437 *os << "] ";
Naseer Ahmede7a77982018-06-04 10:56:04 -0400438 }
439 *os << "} \n";
Naseer Ahmed913502b2017-04-18 16:05:05 -0400440 }
Naseer Ahmede7a77982018-06-04 10:56:04 -0400441 *os << "current mode: " << static_cast<uint32_t>(current_color_mode_) << std::endl;
442 *os << "current render_intent: " << static_cast<uint32_t>(current_render_intent_) << std::endl;
Xu Yang84e61412018-12-06 14:52:16 +0800443 if (curr_dynamic_range_ == kHdrType) {
444 *os << "current dynamic_range: HDR" << std::endl;
445 } else {
446 *os << "current dynamic_range: SDR" << std::endl;
447 }
Naseer Ahmed913502b2017-04-18 16:05:05 -0400448 *os << "current transform: ";
449 for (uint32_t i = 0; i < kColorTransformMatrixCount; i++) {
450 if (i % 4 == 0) {
451 *os << std::endl;
452 }
453 *os << std::fixed << std::setprecision(2) << std::setw(6) << std::setfill(' ')
454 << color_matrix_[i] << " ";
455 }
456 *os << std::endl;
457}
458
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530459HWCDisplay::HWCDisplay(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
460 HWCCallbacks *callbacks, HWCDisplayEventHandler* event_handler,
461 qService::QService *qservice, DisplayType type, hwc2_display_t id,
Gousemoodhin Nadaf087c3102019-01-07 19:34:56 +0530462 int32_t sdm_id, DisplayClass display_class)
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500463 : core_intf_(core_intf),
464 callbacks_(callbacks),
Varun Arora7c8ee542018-05-01 20:58:16 -0700465 event_handler_(event_handler),
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500466 type_(type),
467 id_(id),
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530468 sdm_id_(sdm_id),
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500469 qservice_(qservice),
470 display_class_(display_class) {
Naseer Ahmedd1830402017-03-01 18:38:12 -0500471 buffer_allocator_ = static_cast<HWCBufferAllocator *>(buffer_allocator);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500472}
473
474int HWCDisplay::Init() {
Varun Arora465c1f72018-02-08 16:18:50 -0800475 DisplayError error = kErrorNone;
476
Uday Kiran Pichika5e656b22018-05-15 18:48:24 +0530477 HWCDebugHandler::Get()->GetProperty(ENABLE_NULL_DISPLAY_PROP, &null_display_mode_);
Rajavenu Kyatham50966d82019-08-06 18:02:36 +0530478 HWCDebugHandler::Get()->GetProperty(ENABLE_ASYNC_POWERMODE, &async_power_mode_);
Varun Arora465c1f72018-02-08 16:18:50 -0800479
480 if (null_display_mode_) {
481 DisplayNull *disp_null = new DisplayNull();
482 disp_null->Init();
483 use_metadata_refresh_rate_ = false;
484 display_intf_ = disp_null;
Dileep Marchya4cb86b42018-05-01 19:34:51 +0530485 DLOGI("Enabling null display mode for display type %d", type_);
Varun Arora465c1f72018-02-08 16:18:50 -0800486 } else {
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530487 error = core_intf_->CreateDisplay(sdm_id_, this, &display_intf_);
Varun Arora465c1f72018-02-08 16:18:50 -0800488 if (error != kErrorNone) {
Mathew Joseph Karimpanal23e2da02018-11-13 17:44:43 +0530489 if (kErrorDeviceRemoved == error) {
490 DLOGW("Display creation cancelled. Display %d-%d removed.", sdm_id_, type_);
491 return -ENODEV;
492 } else {
493 DLOGE("Display create failed. Error = %d display_id = %d event_handler = %p disp_intf = %p",
494 error, sdm_id_, this, &display_intf_);
495 return -EINVAL;
496 }
Varun Arora465c1f72018-02-08 16:18:50 -0800497 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500498 }
499
Saurabh Shaha307e8c2017-09-28 18:05:40 -0700500 validated_ = false;
Uday Kiran Pichika5e656b22018-05-15 18:48:24 +0530501 HWCDebugHandler::Get()->GetProperty(DISABLE_HDR, &disable_hdr_handling_);
Arun Kumar K.R2be0bf82017-05-24 15:14:41 +0530502 if (disable_hdr_handling_) {
503 DLOGI("HDR Handling disabled");
504 }
505
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500506 int property_swap_interval = 1;
Uday Kiran Pichika2febe6f2018-05-22 19:23:32 +0530507 HWCDebugHandler::Get()->GetProperty(ZERO_SWAP_INTERVAL, &property_swap_interval);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500508 if (property_swap_interval == 0) {
509 swap_interval_zero_ = true;
510 }
511
Naseer Ahmed42752212017-01-27 17:32:21 -0500512 client_target_ = new HWCLayer(id_, buffer_allocator_);
513
Rajavenu Kyatham40fc5382017-07-12 18:36:55 +0530514 error = display_intf_->GetNumVariableInfoConfigs(&num_configs_);
515 if (error != kErrorNone) {
516 DLOGE("Getting config count failed. Error = %d", error);
517 return -EINVAL;
518 }
519
Pullakavi Srinivas9189e602018-12-19 16:58:07 +0530520 UpdateConfigs();
521
Arun Kumar K.R51be3d12017-03-31 19:54:38 -0700522 tone_mapper_ = new HWCToneMapper(buffer_allocator_);
523
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500524 display_intf_->GetRefreshRateRange(&min_refresh_rate_, &max_refresh_rate_);
525 current_refresh_rate_ = max_refresh_rate_;
Sushil Chauhan409e8442017-06-12 17:43:25 -0700526
527 GetUnderScanConfig();
Sushil Chauhan9735cf82018-07-10 12:06:01 -0700528
529 DisplayConfigFixedInfo fixed_info = {};
530 display_intf_->GetConfig(&fixed_info);
Tharaga Balachandran04192a62018-08-29 16:23:25 -0400531 is_cmd_mode_ = fixed_info.is_cmdmode;
Pullakavi Srinivas984e7032018-10-08 14:52:15 +0530532 partial_update_enabled_ = fixed_info.partial_update || (!fixed_info.is_cmdmode);
Sushil Chauhan9735cf82018-07-10 12:06:01 -0700533 client_target_->SetPartialUpdate(partial_update_enabled_);
534
Sushil Chauhan7bd20662018-08-20 17:51:32 -0700535 int disable_fast_path = 0;
536 HWCDebugHandler::Get()->GetProperty(DISABLE_FAST_PATH, &disable_fast_path);
537 fast_path_enabled_ = !(disable_fast_path == 1);
538
Xu Yang7469c4f2019-11-27 10:25:59 +0800539 game_supported_ = display_intf_->GameEnhanceSupported();
540
Pullakavi Srinivasce3692b2020-02-13 01:14:09 +0530541 DLOGI("Display created with id: %d, game_supported_: %d", UINT32(id_), game_supported_);
Rajavenu Kyatham40fc5382017-07-12 18:36:55 +0530542
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500543 return 0;
544}
545
Pullakavi Srinivas9189e602018-12-19 16:58:07 +0530546void HWCDisplay::UpdateConfigs() {
547 // SF doesnt care about dynamic bit clk support.
548 // Exposing all configs will result in getting/setting of redundant configs.
549
550 // For each config store the corresponding index which client understands.
551 hwc_config_map_.resize(num_configs_);
552
553 for (uint32_t i = 0; i < num_configs_; i++) {
554 DisplayConfigVariableInfo info = {};
555 GetDisplayAttributesForConfig(INT(i), &info);
556 bool config_exists = false;
557 for (auto &config : variable_config_map_) {
558 if (config.second == info) {
559 config_exists = true;
560 hwc_config_map_.at(i) = config.first;
561 break;
562 }
563 }
564
565 if (!config_exists) {
566 variable_config_map_[i] = info;
567 hwc_config_map_.at(i) = i;
568 }
569 }
570
Sushil Chauhan02e34162020-05-12 14:02:56 -0700571 if (num_configs_ != 0) {
572 SetActiveConfigIndex(hwc_config_map_.at(0));
573 }
574
Pullakavi Srinivas9189e602018-12-19 16:58:07 +0530575 // Update num config count.
576 num_configs_ = UINT32(variable_config_map_.size());
577 DLOGI("num_configs = %d", num_configs_);
578}
579
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500580int HWCDisplay::Deinit() {
Varun Arora465c1f72018-02-08 16:18:50 -0800581 if (null_display_mode_) {
582 delete static_cast<DisplayNull *>(display_intf_);
583 display_intf_ = nullptr;
584 } else {
585 DisplayError error = core_intf_->DestroyDisplay(display_intf_);
586 if (error != kErrorNone) {
587 DLOGE("Display destroy failed. Error = %d", error);
588 return -EINVAL;
589 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500590 }
591
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500592 delete client_target_;
Prabhanjan Kandula2e8fba82017-11-13 11:47:10 -0800593 for (auto hwc_layer : layer_set_) {
594 delete hwc_layer;
595 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500596
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700597 if (color_mode_) {
598 color_mode_->DeInit();
599 delete color_mode_;
600 }
601
Varun Arora465c1f72018-02-08 16:18:50 -0800602 if (tone_mapper_) {
603 delete tone_mapper_;
604 tone_mapper_ = nullptr;
605 }
Arun Kumar K.R51be3d12017-03-31 19:54:38 -0700606
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500607 return 0;
608}
609
610// LayerStack operations
611HWC2::Error HWCDisplay::CreateLayer(hwc2_layer_t *out_layer_id) {
Naseer Ahmed42752212017-01-27 17:32:21 -0500612 HWCLayer *layer = *layer_set_.emplace(new HWCLayer(id_, buffer_allocator_));
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500613 layer_map_.emplace(std::make_pair(layer->GetId(), layer));
614 *out_layer_id = layer->GetId();
Naseer Ahmed72dea242016-05-03 19:13:07 -0400615 geometry_changes_ |= GeometryChanges::kAdded;
Saurabh Shaha307e8c2017-09-28 18:05:40 -0700616 validated_ = false;
Saurabh Shahdccc0f42018-01-15 15:59:56 -0800617 layer_stack_invalid_ = true;
Sushil Chauhan9735cf82018-07-10 12:06:01 -0700618 layer->SetPartialUpdate(partial_update_enabled_);
Saurabh Shahdccc0f42018-01-15 15:59:56 -0800619
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500620 return HWC2::Error::None;
621}
622
623HWCLayer *HWCDisplay::GetHWCLayer(hwc2_layer_t layer_id) {
624 const auto map_layer = layer_map_.find(layer_id);
625 if (map_layer == layer_map_.end()) {
Dileep Marchya9e388172019-09-12 11:44:19 +0530626 DLOGW("[%" PRIu64 "] GetLayer(%" PRIu64 ") failed: no such layer", id_, layer_id);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500627 return nullptr;
628 } else {
629 return map_layer->second;
630 }
631}
632
633HWC2::Error HWCDisplay::DestroyLayer(hwc2_layer_t layer_id) {
634 const auto map_layer = layer_map_.find(layer_id);
635 if (map_layer == layer_map_.end()) {
Dileep Marchya9e388172019-09-12 11:44:19 +0530636 DLOGW("[%" PRIu64 "] destroyLayer(%" PRIu64 ") failed: no such layer", id_, layer_id);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500637 return HWC2::Error::BadLayer;
638 }
639 const auto layer = map_layer->second;
640 layer_map_.erase(map_layer);
641 const auto z_range = layer_set_.equal_range(layer);
642 for (auto current = z_range.first; current != z_range.second; ++current) {
643 if (*current == layer) {
644 current = layer_set_.erase(current);
Naseer Ahmede95fe3f2016-06-23 16:56:24 -0400645 delete layer;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500646 break;
647 }
648 }
649
Naseer Ahmed72dea242016-05-03 19:13:07 -0400650 geometry_changes_ |= GeometryChanges::kRemoved;
Saurabh Shaha307e8c2017-09-28 18:05:40 -0700651 validated_ = false;
Saurabh Shahdccc0f42018-01-15 15:59:56 -0800652 layer_stack_invalid_ = true;
653
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500654 return HWC2::Error::None;
655}
656
Naseer Ahmedade4ee62016-10-07 17:07:38 -0400657
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500658void HWCDisplay::BuildLayerStack() {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500659 layer_stack_ = LayerStack();
660 display_rect_ = LayerRect();
661 metadata_refresh_rate_ = 0;
Naseer Ahmeda699e792017-11-09 15:08:31 -0500662 layer_stack_.flags.animating = animating_;
Sushil Chauhan7bd20662018-08-20 17:51:32 -0700663 layer_stack_.flags.fast_path = fast_path_enabled_ && fast_path_composition_;
Gurpreet Singh Dhamia4276882019-04-12 10:30:58 -0700664
665 DTRACE_SCOPED();
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500666 // Add one layer for fb target
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500667 for (auto hwc_layer : layer_set_) {
Prabhanjan Kandula5265b052017-05-30 17:13:40 -0700668 // Reset layer data which SDM may change
669 hwc_layer->ResetPerFrameData();
670
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500671 Layer *layer = hwc_layer->GetSDMLayer();
Naseer Ahmed63c2b5d2016-08-25 16:54:41 -0400672 layer->flags = {}; // Reset earlier flags
Rajavenu Kyatham429c7872018-12-21 15:24:17 +0530673 // Mark all layers to skip, when client target handle is NULL
674 if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::Client ||
675 !client_target_->GetSDMLayer()->input_buffer.buffer_id) {
Naseer Ahmed63c2b5d2016-08-25 16:54:41 -0400676 layer->flags.skip = true;
677 } else if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::SolidColor) {
678 layer->flags.solid_fill = true;
679 }
680
Saurabh Dubey66b807e2018-05-11 10:05:07 +0530681 if (!hwc_layer->IsDataSpaceSupported()) {
Arun Kumar K.R961a28f2017-07-07 15:26:30 +0530682 layer->flags.skip = true;
Arun Kumar K.R961a28f2017-07-07 15:26:30 +0530683 }
Naseer Ahmedade4ee62016-10-07 17:07:38 -0400684
Arun Kumar K.R2c0ff8d2016-06-01 16:56:52 -0700685 // set default composition as GPU for SDM
686 layer->composition = kCompositionGPU;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500687
688 if (swap_interval_zero_) {
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +0530689 layer->input_buffer.acquire_fence = nullptr;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500690 }
691
Pullakavi Srinivase08594d2017-12-28 12:46:02 +0530692 bool is_secure = false;
Naseer Ahmed08add602018-07-18 14:55:00 -0400693 bool is_video = false;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500694 const private_handle_t *handle =
Arun Kumar K.R9c19cdd2016-11-21 16:48:43 -0800695 reinterpret_cast<const private_handle_t *>(layer->input_buffer.buffer_id);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500696 if (handle) {
Naseer Ahmed42752212017-01-27 17:32:21 -0500697 if (handle->buffer_type == BUFFER_TYPE_VIDEO) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500698 layer_stack_.flags.video_present = true;
Naseer Ahmed08add602018-07-18 14:55:00 -0400699 is_video = true;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500700 }
701 // TZ Protected Buffer - L1
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500702 // Gralloc Usage Protected Buffer - L3 - which needs to be treated as Secure & avoid fallback
Pullakavi Srinivase08594d2017-12-28 12:46:02 +0530703 if (handle->flags & private_handle_t::PRIV_FLAGS_PROTECTED_BUFFER ||
704 handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500705 layer_stack_.flags.secure_present = true;
Pullakavi Srinivase08594d2017-12-28 12:46:02 +0530706 is_secure = true;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500707 }
Gousemoodhin Nadaf2db55342018-08-10 15:52:34 +0530708 // UBWC PI format
709 if (handle->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED_PI) {
710 layer->input_buffer.flags.ubwc_pi = true;
711 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500712 }
713
Pullakavi Srinivase08594d2017-12-28 12:46:02 +0530714 if (layer->input_buffer.flags.secure_display) {
Ramkumar Radhakrishnan4f6ded32019-06-11 15:44:48 -0700715 layer_stack_.flags.secure_present = true;
Pullakavi Srinivase08594d2017-12-28 12:46:02 +0530716 is_secure = true;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500717 }
718
Ramakant Singhae057092017-08-31 12:34:54 +0530719 if (hwc_layer->IsSingleBuffered() &&
720 !(hwc_layer->IsRotationPresent() || hwc_layer->IsScalingPresent())) {
721 layer->flags.single_buffer = true;
722 layer_stack_.flags.single_buffered_layer_present = true;
723 }
724
Arun Kumar K.R2be0bf82017-05-24 15:14:41 +0530725 bool hdr_layer = layer->input_buffer.color_metadata.colorPrimaries == ColorPrimaries_BT2020 &&
726 (layer->input_buffer.color_metadata.transfer == Transfer_SMPTE_ST2084 ||
727 layer->input_buffer.color_metadata.transfer == Transfer_HLG);
Arun Kumar K.R953fba62018-11-15 15:56:32 +0530728 if (hdr_layer && !disable_hdr_handling_) {
Gousemoodhin Nadaf839f29d2018-06-04 10:56:04 -0400729 // Dont honor HDR when its handling is disabled
Arun Kumar K.R51be3d12017-03-31 19:54:38 -0700730 layer->input_buffer.flags.hdr = true;
731 layer_stack_.flags.hdr_present = true;
732 }
733
Pullakavi Srinivasc6a110e2018-04-19 20:32:13 +0530734 if (hwc_layer->IsNonIntegralSourceCrop() && !is_secure && !hdr_layer &&
Naseer Ahmed08add602018-07-18 14:55:00 -0400735 !layer->flags.single_buffer && !layer->flags.solid_fill && !is_video) {
Pullakavi Srinivase08594d2017-12-28 12:46:02 +0530736 layer->flags.skip = true;
737 }
738
Pullakavi Srinivasf33ee312019-05-10 17:18:19 +0530739 if (!layer->flags.skip &&
740 (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::Cursor)) {
741 // Currently we support only one HWCursor & only at top most z-order
742 if ((*layer_set_.rbegin())->GetId() == hwc_layer->GetId()) {
743 layer->flags.cursor = true;
744 layer_stack_.flags.cursor_present = true;
745 }
746 }
747
Pullakavi Srinivase08594d2017-12-28 12:46:02 +0530748 if (layer->flags.skip) {
749 layer_stack_.flags.skip_present = true;
750 }
751
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500752 // TODO(user): Move to a getter if this is needed at other places
753 hwc_rect_t scaled_display_frame = {INT(layer->dst_rect.left), INT(layer->dst_rect.top),
754 INT(layer->dst_rect.right), INT(layer->dst_rect.bottom)};
Ramakant Singh830e9852017-07-29 21:31:09 +0530755 if (hwc_layer->GetGeometryChanges() & kDisplayFrame) {
756 ApplyScanAdjustment(&scaled_display_frame);
757 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500758 hwc_layer->SetLayerDisplayFrame(scaled_display_frame);
Ramakant Singh830e9852017-07-29 21:31:09 +0530759 hwc_layer->ResetPerFrameData();
Naseer Ahmed16c72b92016-07-22 20:02:31 -0400760 // SDM requires these details even for solid fill
761 if (layer->flags.solid_fill) {
Arun Kumar K.R9c19cdd2016-11-21 16:48:43 -0800762 LayerBuffer *layer_buffer = &layer->input_buffer;
Naseer Ahmed16c72b92016-07-22 20:02:31 -0400763 layer_buffer->width = UINT32(layer->dst_rect.right - layer->dst_rect.left);
764 layer_buffer->height = UINT32(layer->dst_rect.bottom - layer->dst_rect.top);
Naseer Ahmedebf4a0d2016-11-16 16:24:13 -0500765 layer_buffer->unaligned_width = layer_buffer->width;
766 layer_buffer->unaligned_height = layer_buffer->height;
Naseer Ahmed16c72b92016-07-22 20:02:31 -0400767 layer->src_rect.left = 0;
768 layer->src_rect.top = 0;
769 layer->src_rect.right = layer_buffer->width;
770 layer->src_rect.bottom = layer_buffer->height;
771 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500772
Pullakavi Srinivas3dbb0d92018-03-07 15:15:14 +0530773 if (hwc_layer->HasMetaDataRefreshRate() && layer->frame_rate > metadata_refresh_rate_) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500774 metadata_refresh_rate_ = SanitizeRefreshRate(layer->frame_rate);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500775 }
Pullakavi Srinivas3dbb0d92018-03-07 15:15:14 +0530776
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500777 display_rect_ = Union(display_rect_, layer->dst_rect);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500778 geometry_changes_ |= hwc_layer->GetGeometryChanges();
Prabhanjan Kandulaf3bc22c2016-08-03 18:59:03 +0530779
780 layer->flags.updating = true;
781 if (layer_set_.size() <= kMaxLayerCount) {
Sushil Chauhan9735cf82018-07-10 12:06:01 -0700782 layer->flags.updating = IsLayerUpdating(hwc_layer);
Prabhanjan Kandulaf3bc22c2016-08-03 18:59:03 +0530783 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500784
Tharaga Balachandran209db582019-03-25 18:56:50 -0400785 if (hwc_layer->IsColorTransformSet()) {
786 layer->flags.color_transform = true;
787 }
788
Pullakavi Srinivasad8bd012019-04-22 17:04:51 +0530789 layer_stack_.flags.mask_present |= layer->input_buffer.flags.mask_layer;
790
Sushil Chauhand1906042019-04-05 14:03:19 -0700791 if ((hwc_layer->GetDeviceSelectedCompositionType() != HWC2::Composition::Device) ||
792 (hwc_layer->GetClientRequestedCompositionType() != HWC2::Composition::Device) ||
793 layer->flags.skip) {
794 layer->update_mask.set(kClientCompRequest);
795 }
796
Xu Yang7469c4f2019-11-27 10:25:59 +0800797 if (game_supported_ && (hwc_layer->GetType() == kLayerGame)) {
Ray Zhang2ee82472019-09-05 02:53:29 +0800798 layer->flags.is_game = true;
799 layer->input_buffer.flags.game = true;
800 }
801
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500802 layer_stack_.layers.push_back(layer);
803 }
Naseer Ahmedade4ee62016-10-07 17:07:38 -0400804
Sushil Chauhan601150c2019-07-24 09:06:45 -0700805 // If layer stack needs Client composition, HWC display gets into InternalValidate state. If
806 // validation gets reset by any other thread in this state, enforce Geometry change to ensure
807 // that Client target gets composed by SF.
808 bool enforce_geometry_change = (validate_state_ == kInternalValidate) && !validated_;
809
Arun Kumar K.R3e89f792016-06-01 17:14:15 -0700810 // TODO(user): Set correctly when SDM supports geometry_changes as bitmask
Sushil Chauhand1906042019-04-05 14:03:19 -0700811
Rajavenu Kyathamef474182019-07-03 15:26:08 +0530812 layer_stack_.flags.geometry_changed = UINT32((geometry_changes_ || enforce_geometry_change ||
813 geometry_changes_on_doze_suspend_) > 0);
Rajavenu Kyathamef474182019-07-03 15:26:08 +0530814 layer_stack_.flags.config_changed = !validated_;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500815 // Append client target to the layer stack
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +0530816 Layer *sdm_client_target = client_target_->GetSDMLayer();
Sushil Chauhan9735cf82018-07-10 12:06:01 -0700817 sdm_client_target->flags.updating = IsLayerUpdating(client_target_);
Arun Kumar K.R5b821552018-12-07 08:00:15 +0530818 // Derive client target dataspace based on the color mode - bug/115482728
819 int32_t client_target_dataspace = GetDataspaceFromColorMode(GetCurrentColorMode());
820 SetClientTargetDataSpace(client_target_dataspace);
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +0530821 layer_stack_.layers.push_back(sdm_client_target);
Sushil Chauhan7cd110d2018-08-24 17:17:55 -0700822
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +0530823 // fall back frame composition to GPU when client target is 10bit
824 // TODO(user): clarify the behaviour from Client(SF) and SDM Extn -
825 // when handling 10bit FBT, as it would affect blending
Sushil Chauhan8008d602018-09-04 14:43:27 -0700826 if (Is10BitFormat(sdm_client_target->input_buffer.format)) {
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +0530827 // Must fall back to client composition
828 MarkLayersForClientComposition();
829 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500830}
831
Arun Kumar K.R536c7d62016-06-14 18:47:39 -0700832void HWCDisplay::BuildSolidFillStack() {
833 layer_stack_ = LayerStack();
834 display_rect_ = LayerRect();
835
836 layer_stack_.layers.push_back(solid_fill_layer_);
837 layer_stack_.flags.geometry_changed = 1U;
838 // Append client target to the layer stack
839 layer_stack_.layers.push_back(client_target_->GetSDMLayer());
840}
841
Ray Zhang2ee82472019-09-05 02:53:29 +0800842HWC2::Error HWCDisplay::SetLayerType(hwc2_layer_t layer_id, IQtiComposerClient::LayerType type) {
843 const auto map_layer = layer_map_.find(layer_id);
844 if (map_layer == layer_map_.end()) {
845 DLOGE("[%" PRIu64 "] SetLayerType failed to find layer", id_);
846 return HWC2::Error::BadLayer;
847 }
848
849 const auto layer = map_layer->second;
850 layer->SetLayerType(type);
851 return HWC2::Error::None;
852}
853
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500854HWC2::Error HWCDisplay::SetLayerZOrder(hwc2_layer_t layer_id, uint32_t z) {
855 const auto map_layer = layer_map_.find(layer_id);
856 if (map_layer == layer_map_.end()) {
Dileep Marchya9e388172019-09-12 11:44:19 +0530857 DLOGW("[%" PRIu64 "] updateLayerZ failed to find layer", id_);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500858 return HWC2::Error::BadLayer;
859 }
860
861 const auto layer = map_layer->second;
862 const auto z_range = layer_set_.equal_range(layer);
863 bool layer_on_display = false;
864 for (auto current = z_range.first; current != z_range.second; ++current) {
865 if (*current == layer) {
866 if ((*current)->GetZ() == z) {
867 // Don't change anything if the Z hasn't changed
868 return HWC2::Error::None;
869 }
870 current = layer_set_.erase(current);
871 layer_on_display = true;
872 break;
873 }
874 }
875
876 if (!layer_on_display) {
877 DLOGE("[%" PRIu64 "] updateLayerZ failed to find layer on display", id_);
878 return HWC2::Error::BadLayer;
879 }
880
881 layer->SetLayerZOrder(z);
882 layer_set_.emplace(layer);
883 return HWC2::Error::None;
884}
885
886HWC2::Error HWCDisplay::SetVsyncEnabled(HWC2::Vsync enabled) {
Pullakavi Srinivasce3692b2020-02-13 01:14:09 +0530887 DLOGV("Display ID: %" PRId64 " enabled: %s", id_, to_string(enabled).c_str());
Naseer Ahmedf5187022017-07-24 16:15:28 -0400888 ATRACE_INT("SetVsyncState ", enabled == HWC2::Vsync::Enable ? 1 : 0);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500889 DisplayError error = kErrorNone;
890
Sushil Chauhandbd8db42020-02-28 13:07:48 -0800891 if (shutdown_pending_ ||
892 (!callbacks_->VsyncCallbackRegistered() && !callbacks_->Vsync_2_4CallbackRegistered())) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500893 return HWC2::Error::None;
894 }
895
896 bool state;
897 if (enabled == HWC2::Vsync::Enable)
898 state = true;
899 else if (enabled == HWC2::Vsync::Disable)
900 state = false;
901 else
902 return HWC2::Error::BadParameter;
903
904 error = display_intf_->SetVSyncState(state);
905
906 if (error != kErrorNone) {
907 if (error == kErrorShutDown) {
908 shutdown_pending_ = true;
909 return HWC2::Error::None;
910 }
911 DLOGE("Failed. enabled = %s, error = %d", to_string(enabled).c_str(), error);
912 return HWC2::Error::BadDisplay;
913 }
914
915 return HWC2::Error::None;
916}
917
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530918void HWCDisplay::PostPowerMode() {
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +0530919 if (release_fence_ == nullptr) {
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530920 return;
921 }
922
923 for (auto hwc_layer : layer_set_) {
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +0530924 shared_ptr<Fence> fence = nullptr;
925 shared_ptr<Fence> merged_fence = nullptr;
926
927 hwc_layer->PopBackReleaseFence(&fence);
928 if (fence) {
929 merged_fence = Fence::Merge(release_fence_, fence);
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530930 } else {
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +0530931 merged_fence = release_fence_;
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530932 }
933 hwc_layer->PushBackReleaseFence(merged_fence);
934 }
935
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530936 fbt_release_fence_ = release_fence_;
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530937}
938
Varun Arora78580b82018-09-10 13:59:57 -0700939HWC2::Error HWCDisplay::SetPowerMode(HWC2::PowerMode mode, bool teardown) {
Pullakavi Srinivasce3692b2020-02-13 01:14:09 +0530940 DLOGV("display = %" PRId64 ", mode = %s", id_, to_string(mode).c_str());
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500941 DisplayState state = kStateOff;
942 bool flush_on_error = flush_on_error_;
943
944 if (shutdown_pending_) {
945 return HWC2::Error::None;
946 }
947
948 switch (mode) {
949 case HWC2::PowerMode::Off:
950 // During power off, all of the buffers are released.
951 // Do not flush until a buffer is successfully submitted again.
952 flush_on_error = false;
953 state = kStateOff;
Arun Kumar K.R51be3d12017-03-31 19:54:38 -0700954 if (tone_mapper_) {
955 tone_mapper_->Terminate();
956 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500957 break;
958 case HWC2::PowerMode::On:
Padmanabhan Komandurua7909a92020-04-07 15:17:09 +0530959 if (color_mode_) {
960 color_mode_->SetApplyMode(true);
961 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500962 state = kStateOn;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500963 break;
964 case HWC2::PowerMode::Doze:
Padmanabhan Komandurua7909a92020-04-07 15:17:09 +0530965 if (color_mode_) {
966 color_mode_->SetApplyMode(true);
967 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500968 state = kStateDoze;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500969 break;
970 case HWC2::PowerMode::DozeSuspend:
971 state = kStateDozeSuspend;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500972 break;
973 default:
974 return HWC2::Error::BadParameter;
975 }
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +0530976 shared_ptr<Fence> release_fence = nullptr;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500977
Naseer Ahmedf5187022017-07-24 16:15:28 -0400978 ATRACE_INT("SetPowerMode ", state);
Varun Arora78580b82018-09-10 13:59:57 -0700979 DisplayError error = display_intf_->SetDisplayState(state, teardown, &release_fence);
Saurabh Shaha307e8c2017-09-28 18:05:40 -0700980 validated_ = false;
Sushil Chauhan409e8442017-06-12 17:43:25 -0700981
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500982 if (error == kErrorNone) {
983 flush_on_error_ = flush_on_error;
984 } else {
985 if (error == kErrorShutDown) {
986 shutdown_pending_ = true;
987 return HWC2::Error::None;
988 }
989 DLOGE("Set state failed. Error = %d", error);
990 return HWC2::Error::BadParameter;
991 }
992
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530993 // Update release fence.
994 release_fence_ = release_fence;
Varun Aroraf027a222018-11-14 17:38:16 -0800995 current_power_mode_ = mode;
Rajavenu Kyatham50966d82019-08-06 18:02:36 +0530996
997 // Close the release fences in synchronous power updates
998 if (!async_power_mode_) {
999 PostPowerMode();
1000 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001001 return HWC2::Error::None;
1002}
1003
1004HWC2::Error HWCDisplay::GetClientTargetSupport(uint32_t width, uint32_t height, int32_t format,
1005 int32_t dataspace) {
Rajavenu Kyathamc79fceb2017-09-01 20:41:43 +05301006 ColorMetaData color_metadata = {};
Rajavenu Kyatham78b20862017-10-30 17:53:30 +05301007 if (dataspace != HAL_DATASPACE_UNKNOWN) {
Arun Kumar K.R4aa2c4c2018-05-14 11:45:00 +05301008 dataspace = TranslateFromLegacyDataspace(dataspace);
Rajavenu Kyatham78b20862017-10-30 17:53:30 +05301009 GetColorPrimary(dataspace, &(color_metadata.colorPrimaries));
1010 GetTransfer(dataspace, &(color_metadata.transfer));
1011 GetRange(dataspace, &(color_metadata.range));
1012 }
Rajavenu Kyathamc79fceb2017-09-01 20:41:43 +05301013
Gousemoodhin Nadafa990d722018-04-04 08:33:43 +05301014 LayerBufferFormat sdm_format = HWCLayer::GetSDMFormat(format, 0);
Rajavenu Kyathamc79fceb2017-09-01 20:41:43 +05301015 if (display_intf_->GetClientTargetSupport(width, height, sdm_format,
1016 color_metadata) != kErrorNone) {
1017 return HWC2::Error::Unsupported;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001018 }
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +05301019
Rajavenu Kyathamc79fceb2017-09-01 20:41:43 +05301020 return HWC2::Error::None;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001021}
1022
Naseer Ahmede7a77982018-06-04 10:56:04 -04001023HWC2::Error HWCDisplay::GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes) {
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301024 if (out_modes == nullptr) {
1025 *out_num_modes = 1;
1026 } else if (out_modes && *out_num_modes > 0) {
1027 *out_num_modes = 1;
Naseer Ahmede7a77982018-06-04 10:56:04 -04001028 out_modes[0] = ColorMode::NATIVE;
Arun Kumar K.R29cd6582016-05-10 19:12:45 -07001029 }
Naseer Ahmede7a77982018-06-04 10:56:04 -04001030 return HWC2::Error::None;
1031}
Arun Kumar K.R29cd6582016-05-10 19:12:45 -07001032
Naseer Ahmede7a77982018-06-04 10:56:04 -04001033HWC2::Error HWCDisplay::GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
1034 RenderIntent *out_intents) {
1035 if (mode != ColorMode::NATIVE) {
1036 return HWC2::Error::Unsupported;
1037 }
1038 if (out_intents == nullptr) {
1039 *out_num_intents = 1;
1040 } else if (out_intents && *out_num_intents > 0) {
1041 *out_num_intents = 1;
1042 out_intents[0] = RenderIntent::COLORIMETRIC;
1043 }
Arun Kumar K.R29cd6582016-05-10 19:12:45 -07001044 return HWC2::Error::None;
1045}
1046
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001047HWC2::Error HWCDisplay::GetDisplayConfigs(uint32_t *out_num_configs, hwc2_config_t *out_configs) {
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301048 if (out_num_configs == nullptr) {
1049 return HWC2::Error::BadParameter;
1050 }
1051
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001052 if (out_configs == nullptr) {
Rajavenu Kyatham40fc5382017-07-12 18:36:55 +05301053 *out_num_configs = num_configs_;
1054 return HWC2::Error::None;
1055 }
1056
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301057 *out_num_configs = std::min(*out_num_configs, num_configs_);
Pullakavi Srinivas9189e602018-12-19 16:58:07 +05301058
1059 // Expose all unique config ids to cleint.
1060 uint32_t i = 0;
1061 for (auto &info : variable_config_map_) {
1062 if (i == *out_num_configs) {
1063 break;
1064 }
1065 out_configs[i++] = info.first;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001066 }
Arun Kumar K.R29cd6582016-05-10 19:12:45 -07001067
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001068 return HWC2::Error::None;
1069}
1070
Naseer Ahmed8584a0f2020-02-19 22:23:30 -05001071HWC2::Error HWCDisplay::GetDisplayAttribute(hwc2_config_t config, HwcAttribute attribute,
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001072 int32_t *out_value) {
Pullakavi Srinivas9189e602018-12-19 16:58:07 +05301073 if (variable_config_map_.find(config) == variable_config_map_.end()) {
Pullakavi Srinivas8b33a282018-11-01 12:45:38 +05301074 DLOGE("Get variable config failed");
Manoj Kumar AVM1e397782020-04-21 17:34:04 -07001075 return HWC2::Error::BadConfig;
Arun Kumar K.R8da7f502016-06-07 17:45:50 -07001076 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001077
Pullakavi Srinivas9189e602018-12-19 16:58:07 +05301078 DisplayConfigVariableInfo variable_config = variable_config_map_.at(config);
Rajavenu Kyathamb6292fb2018-06-08 14:29:19 +05301079
1080 variable_config.x_pixels -= UINT32(window_rect_.right + window_rect_.left);
1081 variable_config.y_pixels -= UINT32(window_rect_.bottom + window_rect_.top);
1082 if (variable_config.x_pixels <= 0 || variable_config.y_pixels <= 0) {
1083 DLOGE("window rects are not within the supported range");
1084 return HWC2::Error::BadDisplay;
1085 }
1086
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001087 switch (attribute) {
Naseer Ahmed8584a0f2020-02-19 22:23:30 -05001088 case HwcAttribute::VSYNC_PERIOD:
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001089 *out_value = INT32(variable_config.vsync_period_ns);
1090 break;
Naseer Ahmed8584a0f2020-02-19 22:23:30 -05001091 case HwcAttribute::WIDTH:
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001092 *out_value = INT32(variable_config.x_pixels);
1093 break;
Naseer Ahmed8584a0f2020-02-19 22:23:30 -05001094 case HwcAttribute::HEIGHT:
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001095 *out_value = INT32(variable_config.y_pixels);
1096 break;
Naseer Ahmed8584a0f2020-02-19 22:23:30 -05001097 case HwcAttribute::DPI_X:
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001098 *out_value = INT32(variable_config.x_dpi * 1000.0f);
1099 break;
Naseer Ahmed8584a0f2020-02-19 22:23:30 -05001100 case HwcAttribute::DPI_Y:
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001101 *out_value = INT32(variable_config.y_dpi * 1000.0f);
1102 break;
Naseer Ahmed8584a0f2020-02-19 22:23:30 -05001103 case HwcAttribute::CONFIG_GROUP:
Sushil Chauhanf8541202020-02-03 23:14:36 -08001104 *out_value = GetDisplayConfigGroup(variable_config);
1105 break;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001106 default:
Naseer Ahmed8584a0f2020-02-19 22:23:30 -05001107 DLOGW("Spurious attribute type = %s", composer_V2_4::toString(attribute).c_str());
Naseer Ahmedf937bd02017-04-03 19:10:28 -04001108 *out_value = -1;
Naseer Ahmed8584a0f2020-02-19 22:23:30 -05001109 return HWC2::Error::BadParameter;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001110 }
1111
1112 return HWC2::Error::None;
1113}
1114
1115HWC2::Error HWCDisplay::GetDisplayName(uint32_t *out_size, char *out_name) {
1116 // TODO(user): Get panel name and EDID name and populate it here
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301117 if (out_size == nullptr) {
1118 return HWC2::Error::BadParameter;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001119 }
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301120
1121 std::string name;
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +05301122 switch (type_) {
1123 case kBuiltIn:
1124 name = "Built-in Display";
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301125 break;
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +05301126 case kPluggable:
1127 name = "Pluggable Display";
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301128 break;
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +05301129 case kVirtual:
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301130 name = "Virtual Display";
1131 break;
1132 default:
1133 name = "Unknown";
1134 break;
1135 }
1136
1137 if (out_name == nullptr) {
1138 *out_size = UINT32(name.size()) + 1;
1139 } else {
1140 *out_size = std::min((UINT32(name.size()) + 1), *out_size);
1141 if (*out_size > 0) {
Ravikanth Tunikie8501fc2018-08-10 17:46:15 +05301142 strlcpy(out_name, name.c_str(), *out_size);
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301143 out_name[*out_size - 1] = '\0';
1144 } else {
1145 DLOGW("Invalid size requested");
1146 }
1147 }
1148
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001149 return HWC2::Error::None;
1150}
1151
1152HWC2::Error HWCDisplay::GetDisplayType(int32_t *out_type) {
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +05301153 if (out_type == nullptr) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001154 return HWC2::Error::BadParameter;
1155 }
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +05301156
1157 *out_type = HWC2_DISPLAY_TYPE_PHYSICAL;
1158
1159 return HWC2::Error::None;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001160}
1161
Naseer Ahmeda6782e42018-06-04 10:56:04 -04001162HWC2::Error HWCDisplay::GetPerFrameMetadataKeys(uint32_t *out_num_keys,
1163 PerFrameMetadataKey *out_keys) {
1164 if (out_num_keys == nullptr) {
1165 return HWC2::Error::BadParameter;
1166 }
Gousemoodhin Nadaf4b096d02019-10-24 15:39:59 +05301167
1168 DisplayConfigFixedInfo fixed_info = {};
1169 display_intf_->GetConfig(&fixed_info);
1170 uint32_t num_keys = 0;
1171 if (fixed_info.hdr_plus_supported) {
1172 num_keys = UINT32(PerFrameMetadataKey::HDR10_PLUS_SEI) + 1;
1173 } else {
1174 num_keys = UINT32(PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL) + 1;
1175 }
1176 if (out_keys == nullptr) {
1177 *out_num_keys = num_keys;
1178 } else {
1179 uint32_t max_out_key_elements = std::min(*out_num_keys, num_keys);
1180 for (int32_t i = 0; i < max_out_key_elements; i++) {
1181 out_keys[i] = static_cast<PerFrameMetadataKey>(i);
1182 }
Naseer Ahmeda6782e42018-06-04 10:56:04 -04001183 }
1184 return HWC2::Error::None;
1185}
1186
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001187HWC2::Error HWCDisplay::GetActiveConfig(hwc2_config_t *out_config) {
Rajavenu Kyatham40fc5382017-07-12 18:36:55 +05301188 if (out_config == nullptr) {
1189 return HWC2::Error::BadDisplay;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001190 }
Rajavenu Kyatham40fc5382017-07-12 18:36:55 +05301191
Pullakavi Srinivas81fee962019-07-26 15:49:32 +05301192 if (pending_config_) {
1193 *out_config = pending_config_index_;
1194 } else {
1195 GetActiveDisplayConfig(out_config);
1196 }
1197
Pullakavi Srinivas9189e602018-12-19 16:58:07 +05301198 if (*out_config < hwc_config_map_.size()) {
1199 *out_config = hwc_config_map_.at(*out_config);
1200 }
Rajavenu Kyatham40fc5382017-07-12 18:36:55 +05301201 return HWC2::Error::None;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001202}
1203
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05301204HWC2::Error HWCDisplay::SetClientTarget(buffer_handle_t target, shared_ptr<Fence> acquire_fence,
Naseer Ahmeda20c4c02016-06-03 17:48:28 -04001205 int32_t dataspace, hwc_region_t damage) {
Naseer Ahmed093fd322016-05-03 22:22:09 -04001206 // TODO(user): SurfaceFlinger gives us a null pointer here when doing full SDE composition
1207 // The error is problematic for layer caching as it would overwrite our cached client target.
1208 // Reported bug 28569722 to resolve this.
1209 // For now, continue to use the last valid buffer reported to us for layer caching.
1210 if (target == nullptr) {
1211 return HWC2::Error::None;
1212 }
Naseer Ahmede3f007a2016-06-07 18:13:28 -04001213
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05301214 if (acquire_fence == nullptr) {
Pullakavi Srinivascfe1b672020-05-20 10:46:19 +05301215 DLOGV_IF(kTagClient, "Re-using cached buffer");
Naseer Ahmede3f007a2016-06-07 18:13:28 -04001216 }
1217
Namit Solanki1ec25242017-10-18 16:45:22 +05301218 Layer *sdm_layer = client_target_->GetSDMLayer();
Mahesh Aiaf3a1f992019-01-16 13:07:42 -08001219 sdm_layer->frame_rate = std::min(current_refresh_rate_, HWCDisplay::GetThrottlingRefreshRate());
Naseer Ahmeda20c4c02016-06-03 17:48:28 -04001220 client_target_->SetLayerSurfaceDamage(damage);
Arun Kumar K.R5b821552018-12-07 08:00:15 +05301221 int translated_dataspace = TranslateFromLegacyDataspace(dataspace);
1222 if (client_target_->GetLayerDataspace() != translated_dataspace) {
1223 DLOGW("New Dataspace = %d not matching Dataspace from color mode = %d",
1224 translated_dataspace, client_target_->GetLayerDataspace());
1225 return HWC2::Error::BadParameter;
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +05301226 }
Saurabh Dubey66b807e2018-05-11 10:05:07 +05301227 client_target_->SetLayerBuffer(target, acquire_fence);
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +05301228
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001229 return HWC2::Error::None;
1230}
1231
1232HWC2::Error HWCDisplay::SetActiveConfig(hwc2_config_t config) {
Gurpreet Singh Dhamia4276882019-04-12 10:30:58 -07001233 DTRACE_SCOPED();
1234
Pullakavi Srinivas7bdcc762020-03-06 12:41:36 +05301235 // Cache refresh rate set by client.
1236 DisplayConfigVariableInfo info = {};
1237 GetDisplayAttributesForConfig(INT(config), &info);
1238 active_refresh_rate_ = info.fps;
1239
Pullakavi Srinivas81fee962019-07-26 15:49:32 +05301240 hwc2_config_t current_config = 0;
1241 GetActiveConfig(&current_config);
1242 if (current_config == config) {
1243 return HWC2::Error::None;
Naseer Ahmedf937bd02017-04-03 19:10:28 -04001244 }
Naseer Ahmedd7b8c512019-04-17 20:10:36 -04001245 DLOGI("Active configuration changed to: %d", config);
Pullakavi Srinivas81fee962019-07-26 15:49:32 +05301246
1247 // Store config index to be applied upon refresh.
1248 pending_config_ = true;
1249 pending_config_index_ = config;
1250
Saurabh Shaha307e8c2017-09-28 18:05:40 -07001251 validated_ = false;
Pullakavi Srinivas81fee962019-07-26 15:49:32 +05301252
1253 // Trigger refresh. This config gets applied on next commit.
1254 callbacks_->Refresh(id_);
1255
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001256 return HWC2::Error::None;
1257}
1258
Arun Kumar K.R8da7f502016-06-07 17:45:50 -07001259DisplayError HWCDisplay::SetMixerResolution(uint32_t width, uint32_t height) {
1260 return kErrorNotSupported;
1261}
1262
Sushil Chauhan267a6192018-06-06 18:41:47 -07001263HWC2::Error HWCDisplay::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type,
1264 int32_t format, bool post_processed) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001265 dump_frame_count_ = count;
1266 dump_frame_index_ = 0;
1267 dump_input_layers_ = ((bit_mask_layer_type & (1 << INPUT_LAYER_DUMP)) != 0);
1268
Arun Kumar K.R51be3d12017-03-31 19:54:38 -07001269 if (tone_mapper_) {
1270 tone_mapper_->SetFrameDumpConfig(count);
1271 }
1272
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001273 DLOGI("num_frame_dump %d, input_layer_dump_enable %d", dump_frame_count_, dump_input_layers_);
Saurabh Shaha307e8c2017-09-28 18:05:40 -07001274 validated_ = false;
Mathew Joseph Karimpanaldbd64f82017-10-06 10:13:38 +05301275 return HWC2::Error::None;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001276}
1277
Varun Aroraf027a222018-11-14 17:38:16 -08001278HWC2::PowerMode HWCDisplay::GetCurrentPowerMode() {
1279 return current_power_mode_;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001280}
1281
1282DisplayError HWCDisplay::VSync(const DisplayEventVSync &vsync) {
Sushil Chauhandbd8db42020-02-28 13:07:48 -08001283 if (callbacks_->Vsync_2_4CallbackRegistered()) {
1284 VsyncPeriodNanos vsync_period;
1285 if (GetDisplayVsyncPeriod(&vsync_period) != HWC2::Error::None) {
1286 vsync_period = 0;
1287 }
1288 ATRACE_INT("VsyncPeriod", INT32(vsync_period));
1289 callbacks_->Vsync_2_4(id_, vsync.timestamp, vsync_period);
1290 } else {
1291 callbacks_->Vsync(id_, vsync.timestamp);
1292 }
1293
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001294 return kErrorNone;
1295}
1296
1297DisplayError HWCDisplay::Refresh() {
Varun Aroradff7d8d2019-08-05 18:12:43 -07001298 callbacks_->Refresh(id_);
1299 return kErrorNone;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001300}
1301
1302DisplayError HWCDisplay::CECMessage(char *message) {
1303 if (qservice_) {
1304 qservice_->onCECMessageReceived(message, 0);
1305 } else {
1306 DLOGW("Qservice instance not available.");
1307 }
1308
1309 return kErrorNone;
1310}
1311
Sushil Chauhan409e8442017-06-12 17:43:25 -07001312DisplayError HWCDisplay::HandleEvent(DisplayEvent event) {
1313 switch (event) {
Namit Solanki5b428dc2018-02-27 11:39:05 +05301314 case kIdleTimeout: {
Mathew Joseph Karimpanal4b35b272018-11-27 10:56:49 +05301315 SCOPE_LOCK(HWCSession::locker_[id_]);
Namit Solanki5b428dc2018-02-27 11:39:05 +05301316 if (pending_commit_) {
1317 // If idle timeout event comes in between prepare
1318 // and commit, drop it since device is not really
1319 // idle.
1320 return kErrorNotSupported;
1321 }
1322 validated_ = false;
1323 break;
1324 }
Sushil Chauhanad7b9942020-03-26 19:52:03 -07001325 case kSyncInvalidateDisplay:
Ramakant Singh99370542019-10-15 11:54:39 +05301326 case kThermalEvent: {
Mathew Joseph Karimpanal4b35b272018-11-27 10:56:49 +05301327 SEQUENCE_WAIT_SCOPE_LOCK(HWCSession::locker_[id_]);
Saurabh Shaha307e8c2017-09-28 18:05:40 -07001328 validated_ = false;
1329 } break;
Ramakant Singh99370542019-10-15 11:54:39 +05301330 case kPanelDeadEvent:
Varun Arora7c8ee542018-05-01 20:58:16 -07001331 case kDisplayPowerResetEvent: {
Manoj Kumar AVM92df9782019-11-14 08:36:32 -08001332 // Mutex scope
1333 {
1334 SEQUENCE_WAIT_SCOPE_LOCK(HWCSession::locker_[id_]);
1335 validated_ = false;
1336 }
1337 // TODO(user): Following scenario need to be addressed
1338 // If panel or HW is in bad state for either ESD or HWR, there is no acquired lock between
1339 // this scope and call to DisplayPowerReset.
1340 // Prepare or commit could operate on the display since locker_[id_] is free and most likely
1341 // result in a failure since ESD/HWR has been requested during this time period.
Varun Arora7c8ee542018-05-01 20:58:16 -07001342 if (event_handler_) {
1343 event_handler_->DisplayPowerReset();
1344 } else {
Pullakavi Srinivasce3692b2020-02-13 01:14:09 +05301345 DLOGW("Cannot execute DisplayPowerReset (client_id = %" PRId64 "), event_handler_ is null",
Varun Aroraf027a222018-11-14 17:38:16 -08001346 id_);
Varun Arora7c8ee542018-05-01 20:58:16 -07001347 }
1348 } break;
Sushil Chauhan43102c72019-06-21 02:06:24 -07001349 case kIdlePowerCollapse:
1350 break;
Sushil Chauhanad7b9942020-03-26 19:52:03 -07001351 case kInvalidateDisplay:
1352 validated_ = false;
1353 break;
Sushil Chauhan409e8442017-06-12 17:43:25 -07001354 default:
1355 DLOGW("Unknown event: %d", event);
1356 break;
1357 }
1358
1359 return kErrorNone;
1360}
1361
Lakshmi Narayana Kalavalae0127eb2019-12-03 11:07:26 -08001362DisplayError HWCDisplay::HistogramEvent(int /* fd */, uint32_t /* blob_fd */) {
1363 return kErrorNone;
1364}
1365
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001366HWC2::Error HWCDisplay::PrepareLayerStack(uint32_t *out_num_types, uint32_t *out_num_requests) {
1367 layer_changes_.clear();
1368 layer_requests_.clear();
Sushil Chauhane3a9fd02017-10-12 18:00:05 -07001369 has_client_composition_ = false;
1370
Gurpreet Singh Dhamia4276882019-04-12 10:30:58 -07001371 DTRACE_SCOPED();
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001372 if (shutdown_pending_) {
Sushil Chauhane3a9fd02017-10-12 18:00:05 -07001373 validated_ = false;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001374 return HWC2::Error::BadDisplay;
1375 }
1376
Sushil Chauhan36c059a2018-06-28 11:39:01 -07001377 if (CanSkipSdmPrepare(out_num_types, out_num_requests)) {
1378 return ((*out_num_types > 0) ? HWC2::Error::HasChanges : HWC2::Error::None);
1379 }
1380
Pullakavi Srinivas3dbb0d92018-03-07 15:15:14 +05301381 UpdateRefreshRate();
Pullakavi Srinivas81fee962019-07-26 15:49:32 +05301382 UpdateActiveConfig();
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -07001383 DisplayError error = display_intf_->Prepare(&layer_stack_);
1384 if (error != kErrorNone) {
1385 if (error == kErrorShutDown) {
1386 shutdown_pending_ = true;
Padmanabhan Komandurue74cf4f2019-04-25 17:38:43 -07001387 } else if (error == kErrorPermission) {
1388 WaitOnPreviousFence();
1389 MarkLayersForGPUBypass();
Rajavenu Kyathamef474182019-07-03 15:26:08 +05301390 geometry_changes_on_doze_suspend_ |= geometry_changes_;
Padmanabhan Komandurue74cf4f2019-04-25 17:38:43 -07001391 } else {
Varun Arora2d1fcb72019-03-21 17:43:06 -07001392 DLOGW("Prepare failed. Error = %d", error);
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -07001393 // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
1394 // so that previous buffer and fences are released, and override the error.
1395 flush_ = true;
Padmanabhan Komandurue74cf4f2019-04-25 17:38:43 -07001396 validated_ = false;
Ramakant Singh635c5552019-03-26 13:06:51 +05301397 // Prepare cycle can fail on a newly connected display if insufficient pipes
1398 // are available at this moment. Trigger refresh so that the other displays
1399 // can free up pipes and a valid content can be attached to virtual display.
1400 callbacks_->Refresh(id_);
Padmanabhan Komandurue74cf4f2019-04-25 17:38:43 -07001401 return HWC2::Error::BadDisplay;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001402 }
Rajavenu Kyatham870b7b22019-11-05 17:58:17 +05301403 } else {
1404 // clear geometry_changes_on_doze_suspend_ on successful prepare.
1405 geometry_changes_on_doze_suspend_ = GeometryChanges::kNone;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001406 }
1407
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001408 for (auto hwc_layer : layer_set_) {
1409 Layer *layer = hwc_layer->GetSDMLayer();
1410 LayerComposition &composition = layer->composition;
1411
Pullakavi Srinivas1ae4acb2019-11-18 19:33:45 +05301412 if (composition == kCompositionSDE || composition == kCompositionStitch) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001413 layer_requests_[hwc_layer->GetId()] = HWC2::LayerRequest::ClearClientTarget;
1414 }
1415
Arun Kumar K.R2c0ff8d2016-06-01 16:56:52 -07001416 HWC2::Composition requested_composition = hwc_layer->GetClientRequestedCompositionType();
Arun Kumar K.R3e89f792016-06-01 17:14:15 -07001417 // Set SDM composition to HWC2 type in HWCLayer
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001418 hwc_layer->SetComposition(composition);
Arun Kumar K.R2c0ff8d2016-06-01 16:56:52 -07001419 HWC2::Composition device_composition = hwc_layer->GetDeviceSelectedCompositionType();
Sushil Chauhane3a9fd02017-10-12 18:00:05 -07001420 if (device_composition == HWC2::Composition::Client) {
1421 has_client_composition_ = true;
1422 }
Arun Kumar K.R2c0ff8d2016-06-01 16:56:52 -07001423 // Update the changes list only if the requested composition is different from SDM comp type
Arun Kumar K.R2c0ff8d2016-06-01 16:56:52 -07001424 if (requested_composition != device_composition) {
1425 layer_changes_[hwc_layer->GetId()] = device_composition;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001426 }
Sushil Chauhan409e8442017-06-12 17:43:25 -07001427 hwc_layer->ResetValidation();
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001428 }
Sushil Chauhane3a9fd02017-10-12 18:00:05 -07001429
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +05301430 client_target_->ResetValidation();
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001431 *out_num_types = UINT32(layer_changes_.size());
1432 *out_num_requests = UINT32(layer_requests_.size());
Sushil Chauhane3a9fd02017-10-12 18:00:05 -07001433 validate_state_ = kNormalValidate;
1434 validated_ = true;
Ramkumar Radhakrishnan9335ef42018-05-15 13:41:33 -07001435 layer_stack_invalid_ = false;
Sushil Chauhane3a9fd02017-10-12 18:00:05 -07001436
1437 return ((*out_num_types > 0) ? HWC2::Error::HasChanges : HWC2::Error::None);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001438}
1439
1440HWC2::Error HWCDisplay::AcceptDisplayChanges() {
Naseer Ahmed06ccd302016-10-25 12:46:33 -04001441 if (layer_set_.empty()) {
1442 return HWC2::Error::None;
1443 }
1444
Saurabh Shaha307e8c2017-09-28 18:05:40 -07001445 if (!validated_) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001446 return HWC2::Error::NotValidated;
1447 }
Naseer Ahmed63c2b5d2016-08-25 16:54:41 -04001448
1449 for (const auto& change : layer_changes_) {
1450 auto hwc_layer = layer_map_[change.first];
1451 auto composition = change.second;
Naseer Ahmed06ccd302016-10-25 12:46:33 -04001452 if (hwc_layer != nullptr) {
1453 hwc_layer->UpdateClientCompositionType(composition);
1454 } else {
1455 DLOGW("Invalid layer: %" PRIu64, change.first);
1456 }
Naseer Ahmed63c2b5d2016-08-25 16:54:41 -04001457 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001458 return HWC2::Error::None;
1459}
1460
1461HWC2::Error HWCDisplay::GetChangedCompositionTypes(uint32_t *out_num_elements,
1462 hwc2_layer_t *out_layers, int32_t *out_types) {
Naseer Ahmedb8bf21b2016-06-17 16:15:47 -04001463 if (layer_set_.empty()) {
1464 return HWC2::Error::None;
1465 }
1466
Saurabh Shaha307e8c2017-09-28 18:05:40 -07001467 if (!validated_) {
Arun Kumar K.R2c0ff8d2016-06-01 16:56:52 -07001468 DLOGW("Display is not validated");
1469 return HWC2::Error::NotValidated;
1470 }
Arun Kumar K.R1018d5b2017-06-08 13:51:05 +05301471
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001472 *out_num_elements = UINT32(layer_changes_.size());
1473 if (out_layers != nullptr && out_types != nullptr) {
1474 int i = 0;
1475 for (auto change : layer_changes_) {
1476 out_layers[i] = change.first;
1477 out_types[i] = INT32(change.second);
1478 i++;
1479 }
1480 }
1481 return HWC2::Error::None;
1482}
1483
1484HWC2::Error HWCDisplay::GetReleaseFences(uint32_t *out_num_elements, hwc2_layer_t *out_layers,
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05301485 std::vector<shared_ptr<Fence>> *out_fences) {
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301486 if (out_num_elements == nullptr) {
1487 return HWC2::Error::BadParameter;
1488 }
1489
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001490 if (out_layers != nullptr && out_fences != nullptr) {
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301491 *out_num_elements = std::min(*out_num_elements, UINT32(layer_set_.size()));
1492 auto it = layer_set_.begin();
1493 for (uint32_t i = 0; i < *out_num_elements; i++, it++) {
1494 auto hwc_layer = *it;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001495 out_layers[i] = hwc_layer->GetId();
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05301496
1497 shared_ptr<Fence> &fence = (*out_fences)[i];
1498 hwc_layer->PopFrontReleaseFence(&fence);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001499 }
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301500 } else {
1501 *out_num_elements = UINT32(layer_set_.size());
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001502 }
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301503
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001504 return HWC2::Error::None;
1505}
1506
1507HWC2::Error HWCDisplay::GetDisplayRequests(int32_t *out_display_requests,
1508 uint32_t *out_num_elements, hwc2_layer_t *out_layers,
1509 int32_t *out_layer_requests) {
Naseer Ahmedb8bf21b2016-06-17 16:15:47 -04001510 if (layer_set_.empty()) {
1511 return HWC2::Error::None;
1512 }
1513
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301514 if (out_display_requests == nullptr || out_num_elements == nullptr) {
1515 return HWC2::Error::BadParameter;
1516 }
1517
Arun Kumar K.R1018d5b2017-06-08 13:51:05 +05301518 // No display requests for now
1519 // Use for sharing blit buffers and
1520 // writing wfd buffer directly to output if there is full GPU composition
1521 // and no color conversion needed
Saurabh Shaha307e8c2017-09-28 18:05:40 -07001522 if (!validated_) {
Naseer Ahmedaddcabf2016-05-04 15:49:29 -04001523 DLOGW("Display is not validated");
1524 return HWC2::Error::NotValidated;
1525 }
Arun Kumar K.R1018d5b2017-06-08 13:51:05 +05301526
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001527 *out_display_requests = 0;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001528 if (out_layers != nullptr && out_layer_requests != nullptr) {
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301529 *out_num_elements = std::min(*out_num_elements, UINT32(layer_requests_.size()));
1530 auto it = layer_requests_.begin();
1531 for (uint32_t i = 0; i < *out_num_elements; i++, it++) {
1532 out_layers[i] = it->first;
1533 out_layer_requests[i] = INT32(it->second);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001534 }
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301535 } else {
1536 *out_num_elements = UINT32(layer_requests_.size());
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001537 }
Rajavenu Kyatham7ac83682016-10-10 18:31:13 +05301538
1539 auto client_target_layer = client_target_->GetSDMLayer();
1540 if (client_target_layer->request.flags.flip_buffer) {
1541 *out_display_requests = INT32(HWC2::DisplayRequest::FlipClientTarget);
1542 }
1543
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001544 return HWC2::Error::None;
1545}
1546
Arun Kumar K.Rf28957a2017-01-10 17:36:52 -08001547HWC2::Error HWCDisplay::GetHdrCapabilities(uint32_t *out_num_types, int32_t *out_types,
1548 float *out_max_luminance,
1549 float *out_max_average_luminance,
1550 float *out_min_luminance) {
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301551 if (out_num_types == nullptr || out_max_luminance == nullptr ||
1552 out_max_average_luminance == nullptr || out_min_luminance == nullptr) {
1553 return HWC2::Error::BadParameter;
1554 }
1555
Arun Kumar K.Rf28957a2017-01-10 17:36:52 -08001556 DisplayConfigFixedInfo fixed_info = {};
1557 display_intf_->GetConfig(&fixed_info);
1558
Sushil Chauhan4fac1962017-05-19 14:00:19 -07001559 if (!fixed_info.hdr_supported) {
1560 *out_num_types = 0;
1561 DLOGI("HDR is not supported");
1562 return HWC2::Error::None;
1563 }
1564
Gousemoodhin Nadaf4b096d02019-10-24 15:39:59 +05301565 uint32_t num_types = 0;
1566 if (fixed_info.hdr_plus_supported) {
1567 num_types = UINT32(Hdr::HDR10_PLUS) - 1;
Arun Kumar K.Rf28957a2017-01-10 17:36:52 -08001568 } else {
Gousemoodhin Nadaf4b096d02019-10-24 15:39:59 +05301569 num_types = UINT32(Hdr::HLG) - 1;
1570 }
1571
1572 // We support HDR10, HLG and HDR10_PLUS.
1573 if (out_types == nullptr) {
1574 *out_num_types = num_types;
1575 } else {
1576 uint32_t max_out_types = std::min(*out_num_types, num_types);
1577 int32_t type = static_cast<int32_t>(Hdr::DOLBY_VISION);
1578 for (int32_t i = 0; i < max_out_types; i++) {
1579 while (type == static_cast<int32_t>(Hdr::DOLBY_VISION) /* Skip list */) {
1580 // Skip the type
1581 type++;
1582 }
1583 if (type > (num_types + 1)) {
1584 break;
1585 }
1586 out_types[i] = type++;
1587 }
Sushil Chauhanaa8be832018-08-31 13:38:20 -07001588 *out_max_luminance = fixed_info.max_luminance;
1589 *out_max_average_luminance = fixed_info.average_luminance;
1590 *out_min_luminance = fixed_info.min_luminance;
Arun Kumar K.Rf28957a2017-01-10 17:36:52 -08001591 }
1592
1593 return HWC2::Error::None;
1594}
1595
1596
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001597HWC2::Error HWCDisplay::CommitLayerStack(void) {
Pullakavi Srinivase52bfff2018-09-04 11:13:17 +05301598 if (flush_) {
1599 return HWC2::Error::None;
1600 }
1601
Gurpreet Singh Dhamia4276882019-04-12 10:30:58 -07001602 DTRACE_SCOPED();
1603
Saurabh Shaha307e8c2017-09-28 18:05:40 -07001604 if (!validated_) {
Pullakavi Srinivasce3692b2020-02-13 01:14:09 +05301605 DLOGV_IF(kTagClient, "Display %" PRIu64 "is not validated", id_);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001606 return HWC2::Error::NotValidated;
1607 }
1608
Saurabh Shah41183042018-01-15 14:55:46 -08001609 if (shutdown_pending_ || layer_set_.empty()) {
1610 return HWC2::Error::None;
1611 }
1612
Padmanabhan Komandurue74cf4f2019-04-25 17:38:43 -07001613 if (skip_commit_) {
Pullakavi Srinivasce3692b2020-02-13 01:14:09 +05301614 DLOGV_IF(kTagClient, "Skipping Refresh on display %" PRIu64 , id_);
Padmanabhan Komandurue74cf4f2019-04-25 17:38:43 -07001615 return HWC2::Error::None;
1616 }
1617
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001618 DumpInputBuffers();
1619
Pullakavi Srinivase52bfff2018-09-04 11:13:17 +05301620 DisplayError error = kErrorUndefined;
1621 int status = 0;
1622 if (tone_mapper_) {
1623 if (NeedsToneMap(layer_stack_)) {
1624 status = tone_mapper_->HandleToneMap(&layer_stack_);
1625 if (status != 0) {
1626 DLOGE("Error handling HDR in ToneMapper");
Arun Kumar K.R51be3d12017-03-31 19:54:38 -07001627 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001628 } else {
Pullakavi Srinivase52bfff2018-09-04 11:13:17 +05301629 tone_mapper_->Terminate();
1630 }
1631 }
Padmanabhan Komanduru13b5e102019-12-03 12:35:09 +05301632
1633 if (elapse_timestamp_) {
1634 layer_stack_.elapse_timestamp = elapse_timestamp_;
1635 }
1636
Pullakavi Srinivase52bfff2018-09-04 11:13:17 +05301637 error = display_intf_->Commit(&layer_stack_);
1638
1639 if (error == kErrorNone) {
1640 // A commit is successfully submitted, start flushing on failure now onwards.
1641 flush_on_error_ = true;
Mathew Joseph Karimpanalabe3b3d2018-11-27 17:25:40 +05301642 first_cycle_ = false;
Pullakavi Srinivase52bfff2018-09-04 11:13:17 +05301643 } else {
1644 if (error == kErrorShutDown) {
1645 shutdown_pending_ = true;
1646 return HWC2::Error::Unsupported;
1647 } else if (error == kErrorNotValidated) {
1648 validated_ = false;
1649 return HWC2::Error::NotValidated;
1650 } else if (error != kErrorPermission) {
1651 DLOGE("Commit failed. Error = %d", error);
1652 // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
1653 // so that previous buffer and fences are released, and override the error.
1654 flush_ = true;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001655 }
1656 }
1657
Sushil Chauhane3a9fd02017-10-12 18:00:05 -07001658 validate_state_ = kSkipValidate;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001659 return HWC2::Error::None;
1660}
1661
Dileep Marchyaad668432019-12-02 10:44:52 +05301662HWC2::Error HWCDisplay::PostCommitLayerStack(shared_ptr<Fence> *out_retire_fence) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001663 auto status = HWC2::Error::None;
1664
1665 // Do no call flush on errors, if a successful buffer is never submitted.
1666 if (flush_ && flush_on_error_) {
Pullakavi Srinivas0a1dba62018-07-02 15:49:11 +05301667 display_intf_->Flush(&layer_stack_);
Saurabh Shaha307e8c2017-09-28 18:05:40 -07001668 validated_ = false;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001669 }
1670
Arun Kumar K.R51be3d12017-03-31 19:54:38 -07001671 if (tone_mapper_ && tone_mapper_->IsActive()) {
1672 tone_mapper_->PostCommit(&layer_stack_);
1673 }
1674
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001675 // TODO(user): No way to set the client target release fence on SF
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05301676 shared_ptr<Fence> client_target_release_fence =
1677 client_target_->GetSDMLayer()->input_buffer.release_fence;
1678 if (client_target_release_fence) {
1679 fbt_release_fence_ = client_target_release_fence;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001680 }
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +05301681 client_target_->ResetGeometryChanges();
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001682
1683 for (auto hwc_layer : layer_set_) {
1684 hwc_layer->ResetGeometryChanges();
1685 Layer *layer = hwc_layer->GetSDMLayer();
Arun Kumar K.R9c19cdd2016-11-21 16:48:43 -08001686 LayerBuffer *layer_buffer = &layer->input_buffer;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001687
1688 if (!flush_) {
1689 // If swapinterval property is set to 0 or for single buffer layers, do not update f/w
1690 // release fences and discard fences from driver
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05301691 if (!swap_interval_zero_ && !layer->flags.single_buffer) {
Pullakavi Srinivasad8bd012019-04-22 17:04:51 +05301692 // It may so happen that layer gets marked to GPU & app layer gets queued
1693 // to MDP for composition. In those scenarios, release fence of buffer should
1694 // have mdp and gpu sync points merged.
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05301695 hwc_layer->PushBackReleaseFence(layer_buffer->release_fence);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001696 }
Saurabh Shah42c8d912017-08-31 17:19:30 -07001697 } else {
Padmanabhan Komandurue74cf4f2019-04-25 17:38:43 -07001698 // In case of flush or display paused, we don't return an error to f/w, so it will
1699 // get a release fence out of the hwc_layer's release fence queue
1700 // We should push a -1 to preserve release fence circulation semantics.
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05301701 hwc_layer->PushBackReleaseFence(nullptr);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001702 }
Saurabh Shah41183042018-01-15 14:55:46 -08001703
1704 layer->request.flags = {};
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001705 }
1706
Saurabh Shah41183042018-01-15 14:55:46 -08001707 client_target_->GetSDMLayer()->request.flags = {};
Pullakavi Srinivas0a1dba62018-07-02 15:49:11 +05301708 // if swapinterval property is set to 0 then close and reset the list retire fence
Dileep Marchyaad668432019-12-02 10:44:52 +05301709 if (!swap_interval_zero_) {
1710 *out_retire_fence = layer_stack_.retire_fence;
Pullakavi Srinivas0a1dba62018-07-02 15:49:11 +05301711 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001712
Pullakavi Srinivas0a1dba62018-07-02 15:49:11 +05301713 if (dump_frame_count_) {
1714 dump_frame_count_--;
1715 dump_frame_index_++;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001716 }
Naseer Ahmedab06a8a2016-07-18 18:39:28 -04001717
Sushil Chauhanec4eb572019-02-07 13:29:42 -08001718 layer_stack_.flags.geometry_changed = false;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001719 geometry_changes_ = GeometryChanges::kNone;
1720 flush_ = false;
Padmanabhan Komandurue74cf4f2019-04-25 17:38:43 -07001721 skip_commit_ = false;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001722
1723 return status;
1724}
1725
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001726void HWCDisplay::SetIdleTimeoutMs(uint32_t timeout_ms) {
1727 return;
1728}
1729
1730DisplayError HWCDisplay::SetMaxMixerStages(uint32_t max_mixer_stages) {
1731 DisplayError error = kErrorNone;
1732
1733 if (display_intf_) {
1734 error = display_intf_->SetMaxMixerStages(max_mixer_stages);
Saurabh Shaha307e8c2017-09-28 18:05:40 -07001735 validated_ = false;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001736 }
1737
1738 return error;
1739}
1740
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001741void HWCDisplay::DumpInputBuffers() {
1742 char dir_path[PATH_MAX];
Gurpreet Singh Dhami5713ad32018-06-08 11:49:10 -04001743 int status;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001744
1745 if (!dump_frame_count_ || flush_ || !dump_input_layers_) {
1746 return;
1747 }
1748
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +05301749 DLOGI("dump_frame_count %d dump_input_layers %d", dump_frame_count_, dump_input_layers_);
Mathew Joseph Karimpanal0a2fff52018-10-17 12:11:07 +05301750 snprintf(dir_path, sizeof(dir_path), "%s/frame_dump_disp_id_%02u_%s", HWCDebugHandler::DumpDir(),
1751 UINT32(id_), GetDisplayString());
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001752
Gurpreet Singh Dhami5713ad32018-06-08 11:49:10 -04001753 status = mkdir(dir_path, 777);
1754 if ((status != 0) && errno != EEXIST) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001755 DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
1756 return;
1757 }
1758
Gurpreet Singh Dhami5713ad32018-06-08 11:49:10 -04001759 // Even if directory exists already, need to explicitly change the permission.
1760 if (chmod(dir_path, 0777) != 0) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001761 DLOGW("Failed to change permissions on %s directory", dir_path);
1762 return;
1763 }
1764
1765 for (uint32_t i = 0; i < layer_stack_.layers.size(); i++) {
1766 auto layer = layer_stack_.layers.at(i);
1767 const private_handle_t *pvt_handle =
Arun Kumar K.R9c19cdd2016-11-21 16:48:43 -08001768 reinterpret_cast<const private_handle_t *>(layer->input_buffer.buffer_id);
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05301769 Fence::Wait(layer->input_buffer.acquire_fence);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001770
Pullakavi Srinivasce3692b2020-02-13 01:14:09 +05301771 DLOGI("Dump layer[%d] of %d pvt_handle %p pvt_handle->base %" PRIx64, i,
1772 UINT32(layer_stack_.layers.size()), pvt_handle, pvt_handle? pvt_handle->base : 0);
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +05301773
Uday Kiran Pichika2ba46dc2017-10-26 11:15:29 +05301774 if (!pvt_handle) {
1775 DLOGE("Buffer handle is null");
Ramakant Singh6c749322018-11-24 16:32:23 +05301776 continue;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001777 }
Uday Kiran Pichika2ba46dc2017-10-26 11:15:29 +05301778
1779 if (!pvt_handle->base) {
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05301780 DisplayError error = buffer_allocator_->MapBuffer(pvt_handle, nullptr);
Uday Kiran Pichika2ba46dc2017-10-26 11:15:29 +05301781 if (error != kErrorNone) {
1782 DLOGE("Failed to map buffer, error = %d", error);
Ramakant Singh6c749322018-11-24 16:32:23 +05301783 continue;
Uday Kiran Pichika2ba46dc2017-10-26 11:15:29 +05301784 }
1785 }
1786
1787 char dump_file_name[PATH_MAX];
1788 size_t result = 0;
1789
1790 snprintf(dump_file_name, sizeof(dump_file_name), "%s/input_layer%d_%dx%d_%s_frame%d.raw",
1791 dir_path, i, pvt_handle->width, pvt_handle->height,
1792 qdutils::GetHALPixelFormatString(pvt_handle->format), dump_frame_index_);
1793
1794 FILE *fp = fopen(dump_file_name, "w+");
1795 if (fp) {
1796 result = fwrite(reinterpret_cast<void *>(pvt_handle->base), pvt_handle->size, 1, fp);
1797 fclose(fp);
1798 }
1799
1800 int release_fence = -1;
1801 DisplayError error = buffer_allocator_->UnmapBuffer(pvt_handle, &release_fence);
1802 if (error != kErrorNone) {
1803 DLOGE("Failed to unmap buffer, error = %d", error);
Ramakant Singh6c749322018-11-24 16:32:23 +05301804 continue;
Uday Kiran Pichika2ba46dc2017-10-26 11:15:29 +05301805 }
1806
1807 DLOGI("Frame Dump %s: is %s", dump_file_name, result ? "Successful" : "Failed");
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001808 }
1809}
1810
Dileep Marchyaad668432019-12-02 10:44:52 +05301811void HWCDisplay::DumpOutputBuffer(const BufferInfo &buffer_info, void *base,
1812 shared_ptr<Fence> &retire_fence) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001813 char dir_path[PATH_MAX];
Gurpreet Singh Dhami5713ad32018-06-08 11:49:10 -04001814 int status;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001815
Mathew Joseph Karimpanal0a2fff52018-10-17 12:11:07 +05301816 snprintf(dir_path, sizeof(dir_path), "%s/frame_dump_disp_id_%02u_%s", HWCDebugHandler::DumpDir(),
1817 UINT32(id_), GetDisplayString());
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001818
Gurpreet Singh Dhami5713ad32018-06-08 11:49:10 -04001819 status = mkdir(dir_path, 777);
1820 if ((status != 0) && errno != EEXIST) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001821 DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
1822 return;
1823 }
1824
Gurpreet Singh Dhami5713ad32018-06-08 11:49:10 -04001825 // Even if directory exists already, need to explicitly change the permission.
1826 if (chmod(dir_path, 0777) != 0) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001827 DLOGW("Failed to change permissions on %s directory", dir_path);
1828 return;
1829 }
1830
1831 if (base) {
1832 char dump_file_name[PATH_MAX];
1833 size_t result = 0;
1834
Dileep Marchyaad668432019-12-02 10:44:52 +05301835 if (Fence::Wait(retire_fence) != kErrorNone) {
1836 DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
1837 return;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001838 }
1839
1840 snprintf(dump_file_name, sizeof(dump_file_name), "%s/output_layer_%dx%d_%s_frame%d.raw",
Gurpreet Singh Dhamif9ea8a82018-06-08 11:54:20 -04001841 dir_path, buffer_info.alloc_buffer_info.aligned_width,
1842 buffer_info.alloc_buffer_info.aligned_height,
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001843 GetFormatString(buffer_info.buffer_config.format), dump_frame_index_);
1844
1845 FILE *fp = fopen(dump_file_name, "w+");
1846 if (fp) {
1847 result = fwrite(base, buffer_info.alloc_buffer_info.size, 1, fp);
1848 fclose(fp);
1849 }
1850
1851 DLOGI("Frame Dump of %s is %s", dump_file_name, result ? "Successful" : "Failed");
1852 }
1853}
1854
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001855const char *HWCDisplay::GetDisplayString() {
1856 switch (type_) {
Mathew Joseph Karimpanal0a2fff52018-10-17 12:11:07 +05301857 case kBuiltIn:
1858 return "builtin";
1859 case kPluggable:
1860 return "pluggable";
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001861 case kVirtual:
1862 return "virtual";
1863 default:
1864 return "invalid";
1865 }
1866}
1867
Padmanabhan Komandurua4bf6062019-10-13 09:04:49 +05301868int HWCDisplay::SetFrameBufferConfig(uint32_t x_pixels, uint32_t y_pixels) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001869 if (x_pixels <= 0 || y_pixels <= 0) {
Naseer Ahmed42fc8d12016-05-11 18:33:57 -04001870 DLOGW("Unsupported config: x_pixels=%d, y_pixels=%d", x_pixels, y_pixels);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001871 return -EINVAL;
1872 }
1873
Arun Kumar K.R8da7f502016-06-07 17:45:50 -07001874 DisplayConfigVariableInfo fb_config;
1875 DisplayError error = display_intf_->GetFrameBufferConfig(&fb_config);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001876 if (error != kErrorNone) {
Arun Kumar K.R8da7f502016-06-07 17:45:50 -07001877 DLOGV("Get frame buffer config failed. Error = %d", error);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001878 return -EINVAL;
1879 }
1880
Arun Kumar K.R8da7f502016-06-07 17:45:50 -07001881 fb_config.x_pixels = x_pixels;
1882 fb_config.y_pixels = y_pixels;
1883
1884 error = display_intf_->SetFrameBufferConfig(fb_config);
1885 if (error != kErrorNone) {
1886 DLOGV("Set frame buffer config failed. Error = %d", error);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001887 return -EINVAL;
1888 }
1889
Rajavenu Kyathamb6292fb2018-06-08 14:29:19 +05301890 // Reduce the src_rect and dst_rect as per FBT config.
1891 // SF sending reduced FBT but here the src_rect is equal to mixer which is
1892 // higher than allocated buffer of FBT.
1893 if (windowed_display_) {
1894 x_pixels -= UINT32(window_rect_.right + window_rect_.left);
1895 y_pixels -= UINT32(window_rect_.bottom + window_rect_.top);
1896 }
1897
1898 if (x_pixels <= 0 || y_pixels <= 0) {
1899 DLOGE("window rects are not within the supported range");
1900 return -EINVAL;
1901 }
1902
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001903 // Create rects to represent the new source and destination crops
1904 LayerRect crop = LayerRect(0, 0, FLOAT(x_pixels), FLOAT(y_pixels));
Ramakant Singh830e9852017-07-29 21:31:09 +05301905 hwc_rect_t scaled_display_frame = {0, 0, INT(x_pixels), INT(y_pixels)};
Padmanabhan Komandurua4bf6062019-10-13 09:04:49 +05301906 auto client_target_layer = client_target_->GetSDMLayer();
1907 client_target_layer->src_rect = crop;
Ramakant Singh830e9852017-07-29 21:31:09 +05301908 ApplyScanAdjustment(&scaled_display_frame);
1909 client_target_->SetLayerDisplayFrame(scaled_display_frame);
1910 client_target_->ResetPerFrameData();
1911
Padmanabhan Komandurua4bf6062019-10-13 09:04:49 +05301912 DLOGI("New framebuffer resolution (%dx%d)", fb_config.x_pixels, fb_config.y_pixels);
1913
1914 return 0;
1915}
1916
1917int HWCDisplay::SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels) {
1918 int error = SetFrameBufferConfig(x_pixels, y_pixels);
1919 if (error < 0) {
1920 DLOGV("SetFrameBufferConfig failed. Error = %d", error);
1921 return error;
1922 }
1923
Rajavenu Kyathamb6292fb2018-06-08 14:29:19 +05301924 if (windowed_display_) {
1925 x_pixels -= UINT32(window_rect_.right + window_rect_.left);
1926 y_pixels -= UINT32(window_rect_.bottom + window_rect_.top);
Rajavenu Kyathamb6292fb2018-06-08 14:29:19 +05301927 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001928 auto client_target_layer = client_target_->GetSDMLayer();
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001929
1930 int aligned_width;
1931 int aligned_height;
Naseer Ahmed42752212017-01-27 17:32:21 -05001932 uint32_t usage = GRALLOC_USAGE_HW_FB;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001933 int format = HAL_PIXEL_FORMAT_RGBA_8888;
Prabhanjan Kandula9e3df622017-07-27 12:35:09 -07001934 int ubwc_disabled = 0;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001935 int flags = 0;
Prabhanjan Kandula9e3df622017-07-27 12:35:09 -07001936
1937 // By default UBWC is enabled and below property is global enable/disable for all
1938 // buffers allocated through gralloc , including framebuffer targets.
Uday Kiran Pichika5e656b22018-05-15 18:48:24 +05301939 HWCDebugHandler::Get()->GetProperty(DISABLE_UBWC_PROP, &ubwc_disabled);
Prabhanjan Kandula9e3df622017-07-27 12:35:09 -07001940 if (!ubwc_disabled) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001941 usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
1942 flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
1943 }
Naseer Ahmed42752212017-01-27 17:32:21 -05001944
Naseer Ahmed42752212017-01-27 17:32:21 -05001945 buffer_allocator_->GetAlignedWidthAndHeight(INT(x_pixels), INT(y_pixels), format, usage,
1946 &aligned_width, &aligned_height);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001947
1948 // TODO(user): How does the dirty region get set on the client target? File bug on Google
1949 client_target_layer->composition = kCompositionGPUTarget;
Gousemoodhin Nadafa990d722018-04-04 08:33:43 +05301950 client_target_layer->input_buffer.format = HWCLayer::GetSDMFormat(format, flags);
Arun Kumar K.R9c19cdd2016-11-21 16:48:43 -08001951 client_target_layer->input_buffer.width = UINT32(aligned_width);
1952 client_target_layer->input_buffer.height = UINT32(aligned_height);
1953 client_target_layer->input_buffer.unaligned_width = x_pixels;
1954 client_target_layer->input_buffer.unaligned_height = y_pixels;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001955 client_target_layer->plane_alpha = 255;
1956
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001957 return 0;
1958}
1959
1960void HWCDisplay::GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
Arun Kumar K.R8da7f502016-06-07 17:45:50 -07001961 DisplayConfigVariableInfo fb_config;
1962 display_intf_->GetFrameBufferConfig(&fb_config);
1963
1964 *x_pixels = fb_config.x_pixels;
1965 *y_pixels = fb_config.y_pixels;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001966}
1967
Arun Kumar K.R8da7f502016-06-07 17:45:50 -07001968DisplayError HWCDisplay::GetMixerResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
1969 return display_intf_->GetMixerResolution(x_pixels, y_pixels);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001970}
1971
1972void HWCDisplay::GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
Arun Kumar K.R8da7f502016-06-07 17:45:50 -07001973 DisplayConfigVariableInfo display_config;
1974 uint32_t active_index = 0;
1975
1976 display_intf_->GetActiveConfig(&active_index);
1977 display_intf_->GetConfig(active_index, &display_config);
1978
1979 *x_pixels = display_config.x_pixels;
1980 *y_pixels = display_config.y_pixels;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001981}
1982
Dileep Marchya6860b2b2017-04-07 15:56:47 +05301983int HWCDisplay::SetDisplayStatus(DisplayStatus display_status) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001984 int status = 0;
1985
1986 switch (display_status) {
1987 case kDisplayStatusResume:
1988 display_paused_ = false;
Anjaneya Prasad Musunuri7a509c12018-11-15 15:54:42 +05301989 status = INT32(SetPowerMode(HWC2::PowerMode::On, false /* teardown */));
1990 break;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001991 case kDisplayStatusOnline:
Varun Arora78580b82018-09-10 13:59:57 -07001992 status = INT32(SetPowerMode(HWC2::PowerMode::On, false /* teardown */));
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001993 break;
1994 case kDisplayStatusPause:
1995 display_paused_ = true;
Anjaneya Prasad Musunuri7a509c12018-11-15 15:54:42 +05301996 status = INT32(SetPowerMode(HWC2::PowerMode::Off, false /* teardown */));
1997 break;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001998 case kDisplayStatusOffline:
Varun Arora78580b82018-09-10 13:59:57 -07001999 status = INT32(SetPowerMode(HWC2::PowerMode::Off, false /* teardown */));
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002000 break;
2001 default:
2002 DLOGW("Invalid display status %d", display_status);
2003 return -EINVAL;
2004 }
2005
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002006 return status;
2007}
2008
2009HWC2::Error HWCDisplay::SetCursorPosition(hwc2_layer_t layer, int x, int y) {
2010 if (shutdown_pending_) {
2011 return HWC2::Error::None;
2012 }
2013
Anjaneya Prasad Musunuri3f974b42018-05-10 15:31:58 +05302014 if (!layer_stack_.flags.cursor_present) {
2015 DLOGW("Cursor layer not present");
2016 return HWC2::Error::BadLayer;
2017 }
2018
Arun Kumar K.R1018d5b2017-06-08 13:51:05 +05302019 HWCLayer *hwc_layer = GetHWCLayer(layer);
2020 if (hwc_layer == nullptr) {
Naseer Ahmedb1e8ea92017-04-18 21:17:34 -04002021 return HWC2::Error::BadLayer;
2022 }
Arun Kumar K.R1018d5b2017-06-08 13:51:05 +05302023 if (hwc_layer->GetDeviceSelectedCompositionType() != HWC2::Composition::Cursor) {
2024 return HWC2::Error::None;
2025 }
Sushil Chauhane3a9fd02017-10-12 18:00:05 -07002026 if ((validate_state_ != kSkipValidate) && validated_) {
Arun Kumar K.R1018d5b2017-06-08 13:51:05 +05302027 // the device is currently in the middle of the validate/present sequence,
2028 // cannot set the Position(as per HWC2 spec)
2029 return HWC2::Error::NotValidated;
2030 }
Naseer Ahmedb1e8ea92017-04-18 21:17:34 -04002031
2032 DisplayState state;
2033 if (display_intf_->GetDisplayState(&state) == kErrorNone) {
2034 if (state != kStateOn) {
2035 return HWC2::Error::None;
2036 }
2037 }
2038
Arun Kumar K.R1018d5b2017-06-08 13:51:05 +05302039 // TODO(user): HWC1.5 was not letting SetCursorPosition before validateDisplay,
2040 // but HWC2.0 doesn't let setting cursor position after validate before present.
2041 // Need to revisit.
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002042
2043 auto error = display_intf_->SetCursorPosition(x, y);
2044 if (error != kErrorNone) {
2045 if (error == kErrorShutDown) {
2046 shutdown_pending_ = true;
2047 return HWC2::Error::None;
2048 }
2049
2050 DLOGE("Failed for x = %d y = %d, Error = %d", x, y, error);
2051 return HWC2::Error::BadDisplay;
2052 }
2053
2054 return HWC2::Error::None;
2055}
2056
2057int HWCDisplay::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
2058 DisplayError error = display_intf_->OnMinHdcpEncryptionLevelChange(min_enc_level);
2059 if (error != kErrorNone) {
2060 DLOGE("Failed. Error = %d", error);
2061 return -1;
2062 }
2063
Saurabh Shaha307e8c2017-09-28 18:05:40 -07002064 validated_ = false;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002065 return 0;
2066}
2067
2068void HWCDisplay::MarkLayersForGPUBypass() {
2069 for (auto hwc_layer : layer_set_) {
2070 auto layer = hwc_layer->GetSDMLayer();
2071 layer->composition = kCompositionSDE;
2072 }
Saurabh Shaha307e8c2017-09-28 18:05:40 -07002073 validated_ = true;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002074}
2075
Arun Kumar K.R29cd6582016-05-10 19:12:45 -07002076void HWCDisplay::MarkLayersForClientComposition() {
2077 // ClientComposition - GPU comp, to acheive this, set skip flag so that
2078 // SDM does not handle this layer and hwc_layer composition will be
2079 // set correctly at the end of Prepare.
Saurabh Dubeyd90a6a42017-10-24 16:28:01 +05302080 DLOGV_IF(kTagClient, "HWC Layers marked for GPU comp");
Arun Kumar K.R29cd6582016-05-10 19:12:45 -07002081 for (auto hwc_layer : layer_set_) {
2082 Layer *layer = hwc_layer->GetSDMLayer();
2083 layer->flags.skip = true;
2084 }
Naseer Ahmed738da072018-01-24 14:41:46 -05002085 layer_stack_.flags.skip_present = true;
Arun Kumar K.R29cd6582016-05-10 19:12:45 -07002086}
2087
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002088void HWCDisplay::ApplyScanAdjustment(hwc_rect_t *display_frame) {
2089}
2090
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002091int HWCDisplay::ToggleScreenUpdates(bool enable) {
2092 display_paused_ = enable ? false : true;
Padmanabhan Komandurue74cf4f2019-04-25 17:38:43 -07002093 callbacks_->Refresh(id_);
Saurabh Shaha307e8c2017-09-28 18:05:40 -07002094 validated_ = false;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002095 return 0;
2096}
2097
2098int HWCDisplay::ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
2099 PPDisplayAPIPayload *out_payload,
2100 PPPendingParams *pending_action) {
2101 int ret = 0;
2102
2103 if (display_intf_)
2104 ret = display_intf_->ColorSVCRequestRoute(in_payload, out_payload, pending_action);
2105 else
2106 ret = -EINVAL;
2107
2108 return ret;
2109}
2110
Arun Kumar K.R536c7d62016-06-14 18:47:39 -07002111void HWCDisplay::SolidFillPrepare() {
2112 if (solid_fill_enable_) {
2113 if (solid_fill_layer_ == NULL) {
2114 // Create a dummy layer here
2115 solid_fill_layer_ = new Layer();
Arun Kumar K.R536c7d62016-06-14 18:47:39 -07002116 }
2117 uint32_t primary_width = 0, primary_height = 0;
2118 GetMixerResolution(&primary_width, &primary_height);
2119
Arun Kumar K.R9c19cdd2016-11-21 16:48:43 -08002120 LayerBuffer *layer_buffer = &solid_fill_layer_->input_buffer;
Arun Kumar K.R536c7d62016-06-14 18:47:39 -07002121 layer_buffer->width = primary_width;
2122 layer_buffer->height = primary_height;
Ramkumar Radhakrishnanb27735f2016-08-26 22:37:23 -07002123 layer_buffer->unaligned_width = primary_width;
2124 layer_buffer->unaligned_height = primary_height;
Arun Kumar K.R536c7d62016-06-14 18:47:39 -07002125
Arun Kumar K.R536c7d62016-06-14 18:47:39 -07002126 solid_fill_layer_->composition = kCompositionGPU;
Gopikrishnaiah Anandanb032efb2017-08-30 12:49:46 -07002127 solid_fill_layer_->src_rect = solid_fill_rect_;
2128 solid_fill_layer_->dst_rect = solid_fill_rect_;
Arun Kumar K.R536c7d62016-06-14 18:47:39 -07002129
2130 solid_fill_layer_->blending = kBlendingPremultiplied;
Gopikrishnaiah Anandancc123062017-07-31 17:21:03 -07002131 solid_fill_layer_->solid_fill_color = 0;
2132 solid_fill_layer_->solid_fill_info.bit_depth = solid_fill_color_.bit_depth;
2133 solid_fill_layer_->solid_fill_info.red = solid_fill_color_.red;
2134 solid_fill_layer_->solid_fill_info.blue = solid_fill_color_.blue;
2135 solid_fill_layer_->solid_fill_info.green = solid_fill_color_.green;
2136 solid_fill_layer_->solid_fill_info.alpha = solid_fill_color_.alpha;
Arun Kumar K.R536c7d62016-06-14 18:47:39 -07002137 solid_fill_layer_->frame_rate = 60;
2138 solid_fill_layer_->visible_regions.push_back(solid_fill_layer_->dst_rect);
2139 solid_fill_layer_->flags.updating = 1;
2140 solid_fill_layer_->flags.solid_fill = true;
2141 } else {
2142 // delete the dummy layer
Arun Kumar K.R536c7d62016-06-14 18:47:39 -07002143 delete solid_fill_layer_;
2144 solid_fill_layer_ = NULL;
2145 }
2146
2147 if (solid_fill_enable_ && solid_fill_layer_) {
2148 BuildSolidFillStack();
2149 MarkLayersForGPUBypass();
2150 }
2151
2152 return;
2153}
2154
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002155int HWCDisplay::GetVisibleDisplayRect(hwc_rect_t *visible_rect) {
2156 if (!IsValid(display_rect_)) {
2157 return -EINVAL;
2158 }
2159
2160 visible_rect->left = INT(display_rect_.left);
2161 visible_rect->top = INT(display_rect_.top);
2162 visible_rect->right = INT(display_rect_.right);
2163 visible_rect->bottom = INT(display_rect_.bottom);
Pullakavi Srinivasce3692b2020-02-13 01:14:09 +05302164 DLOGI("Visible Display Rect(%d %d %d %d)", visible_rect->left, visible_rect->top,
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002165 visible_rect->right, visible_rect->bottom);
2166
2167 return 0;
2168}
2169
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -07002170int HWCDisplay::HandleSecureSession(const std::bitset<kSecureMax> &secure_sessions,
2171 bool *power_on_pending) {
2172 if (!power_on_pending) {
2173 return -EINVAL;
Ramakant Singh46a1bee2017-09-22 21:26:21 +05302174 }
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -07002175
2176 if (active_secure_sessions_[kSecureDisplay] != secure_sessions[kSecureDisplay]) {
2177 if (secure_sessions[kSecureDisplay]) {
Mathew Joseph Karimpanalb1c15862019-07-04 11:14:24 +05302178 pending_power_mode_ = current_power_mode_;
Varun Arora78580b82018-09-10 13:59:57 -07002179 HWC2::Error error = SetPowerMode(HWC2::PowerMode::Off, true /* teardown */);
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -07002180 if (error != HWC2::Error::None) {
2181 DLOGE("SetPowerMode failed. Error = %d", error);
2182 }
2183 } else {
2184 *power_on_pending = true;
2185 }
2186
Pullakavi Srinivasce3692b2020-02-13 01:14:09 +05302187 DLOGI("SecureDisplay state changed from %d to %d for display %" PRId64 "-%d",
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -07002188 active_secure_sessions_.test(kSecureDisplay), secure_sessions.test(kSecureDisplay),
Mathew Joseph Karimpanalb1c15862019-07-04 11:14:24 +05302189 id_, type_);
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -07002190 }
2191 active_secure_sessions_ = secure_sessions;
2192 return 0;
2193}
2194
2195int HWCDisplay::GetActiveSecureSession(std::bitset<kSecureMax> *secure_sessions) {
2196 if (!secure_sessions) {
2197 return -1;
2198 }
2199 secure_sessions->reset();
2200 for (auto hwc_layer : layer_set_) {
2201 Layer *layer = hwc_layer->GetSDMLayer();
2202 if (layer->input_buffer.flags.secure_camera) {
2203 secure_sessions->set(kSecureCamera);
2204 }
2205 if (layer->input_buffer.flags.secure_display) {
2206 secure_sessions->set(kSecureDisplay);
2207 }
2208 }
2209 return 0;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002210}
2211
Dileep Marchya6860b2b2017-04-07 15:56:47 +05302212int HWCDisplay::SetActiveDisplayConfig(uint32_t config) {
Pullakavi Srinivas8b33a282018-11-01 12:45:38 +05302213 uint32_t current_config = 0;
2214 display_intf_->GetActiveConfig(&current_config);
2215 if (config == current_config) {
Ramkumar Radhakrishnan3dcf8a22017-11-27 14:53:06 -08002216 return 0;
2217 }
Ramkumar Radhakrishnan3dcf8a22017-11-27 14:53:06 -08002218
Pullakavi Srinivas8b33a282018-11-01 12:45:38 +05302219 validated_ = false;
Sushil Chauhan02e34162020-05-12 14:02:56 -07002220 DisplayError error = display_intf_->SetActiveConfig(config);
2221 if (error != kErrorNone) {
2222 DLOGE("Failed to set %d config! Error: %d", config, error);
2223 return -EINVAL;
2224 }
Ramkumar Radhakrishnan3dcf8a22017-11-27 14:53:06 -08002225
Sushil Chauhan02e34162020-05-12 14:02:56 -07002226 SetActiveConfigIndex(config);
Ramkumar Radhakrishnan3dcf8a22017-11-27 14:53:06 -08002227 return 0;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002228}
2229
2230int HWCDisplay::GetActiveDisplayConfig(uint32_t *config) {
2231 return display_intf_->GetActiveConfig(config) == kErrorNone ? 0 : -1;
2232}
2233
2234int HWCDisplay::GetDisplayConfigCount(uint32_t *count) {
2235 return display_intf_->GetNumVariableInfoConfigs(count) == kErrorNone ? 0 : -1;
2236}
2237
Arun Kumar K.R8da7f502016-06-07 17:45:50 -07002238int HWCDisplay::GetDisplayAttributesForConfig(int config,
2239 DisplayConfigVariableInfo *display_attributes) {
2240 return display_intf_->GetConfig(UINT32(config), display_attributes) == kErrorNone ? 0 : -1;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002241}
2242
Ramakant Singh5db0dfb2017-08-23 12:34:57 +05302243uint32_t HWCDisplay::GetUpdatingLayersCount(void) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002244 uint32_t updating_count = 0;
2245
Arun Kumar K.R536c7d62016-06-14 18:47:39 -07002246 for (uint i = 0; i < layer_stack_.layers.size(); i++) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002247 auto layer = layer_stack_.layers.at(i);
2248 if (layer->flags.updating) {
2249 updating_count++;
2250 }
2251 }
2252
Ramakant Singh5db0dfb2017-08-23 12:34:57 +05302253 return updating_count;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002254}
2255
Sushil Chauhan9735cf82018-07-10 12:06:01 -07002256bool HWCDisplay::IsLayerUpdating(HWCLayer *hwc_layer) {
2257 auto layer = hwc_layer->GetSDMLayer();
Arun Kumar K.R3e89f792016-06-01 17:14:15 -07002258 // Layer should be considered updating if
2259 // a) layer is in single buffer mode, or
2260 // b) valid dirty_regions(android specific hint for updating status), or
2261 // c) layer stack geometry has changed (TODO(user): Remove when SDM accepts
2262 // geometry_changed as bit fields).
Sushil Chauhan9735cf82018-07-10 12:06:01 -07002263 return (layer->flags.single_buffer || hwc_layer->IsSurfaceUpdated() ||
Arun Kumar K.R3e89f792016-06-01 17:14:15 -07002264 geometry_changes_);
2265}
2266
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002267uint32_t HWCDisplay::SanitizeRefreshRate(uint32_t req_refresh_rate) {
2268 uint32_t refresh_rate = req_refresh_rate;
2269
2270 if (refresh_rate < min_refresh_rate_) {
2271 // Pick the next multiple of request which is within the range
2272 refresh_rate =
2273 (((min_refresh_rate_ / refresh_rate) + ((min_refresh_rate_ % refresh_rate) ? 1 : 0)) *
2274 refresh_rate);
2275 }
2276
2277 if (refresh_rate > max_refresh_rate_) {
2278 refresh_rate = max_refresh_rate_;
2279 }
2280
2281 return refresh_rate;
2282}
2283
2284DisplayClass HWCDisplay::GetDisplayClass() {
2285 return display_class_;
2286}
2287
Dileep Marchya58928122020-01-28 12:16:51 +05302288void HWCDisplay::Dump(std::ostringstream *os) {
2289 *os << "\n------------HWC----------------\n";
2290 *os << "HWC2 display_id: " << id_ << std::endl;
Naseer Ahmed1fd59ea2016-05-05 13:59:23 -04002291 for (auto layer : layer_set_) {
2292 auto sdm_layer = layer->GetSDMLayer();
Arun Kumar K.Rf641dff2016-06-16 13:20:02 -07002293 auto transform = sdm_layer->transform;
Dileep Marchya58928122020-01-28 12:16:51 +05302294 *os << "layer: " << std::setw(4) << layer->GetId();
2295 *os << " z: " << layer->GetZ();
2296 *os << " composition: " <<
Naseer Ahmed85ca1202017-04-18 15:31:59 -04002297 to_string(layer->GetClientRequestedCompositionType()).c_str();
Dileep Marchya58928122020-01-28 12:16:51 +05302298 *os << "/" <<
Naseer Ahmed85ca1202017-04-18 15:31:59 -04002299 to_string(layer->GetDeviceSelectedCompositionType()).c_str();
Dileep Marchya58928122020-01-28 12:16:51 +05302300 *os << " alpha: " << std::to_string(sdm_layer->plane_alpha).c_str();
2301 *os << " format: " << std::setw(22) << GetFormatString(sdm_layer->input_buffer.format);
2302 *os << " dataspace:" << std::hex << "0x" << std::setw(8) << std::setfill('0')
2303 << layer->GetLayerDataspace() << std::dec << std::setfill(' ');
2304 *os << " transform: " << transform.rotation << "/" << transform.flip_horizontal <<
Naseer Ahmed85ca1202017-04-18 15:31:59 -04002305 "/"<< transform.flip_vertical;
Dileep Marchya58928122020-01-28 12:16:51 +05302306 *os << " buffer_id: " << std::hex << "0x" << sdm_layer->input_buffer.buffer_id << std::dec;
2307 *os << " secure: " << layer->IsProtected()
2308 << std::endl;
Naseer Ahmed1fd59ea2016-05-05 13:59:23 -04002309 }
Saurabh Shah9c224a32017-11-09 12:17:44 -08002310
Gousemoodhin Nadafa08db9e2018-07-16 14:25:09 +05302311 if (has_client_composition_) {
Dileep Marchya58928122020-01-28 12:16:51 +05302312 *os << "\n---------client target---------\n";
Gousemoodhin Nadafa08db9e2018-07-16 14:25:09 +05302313 auto sdm_layer = client_target_->GetSDMLayer();
Dileep Marchya58928122020-01-28 12:16:51 +05302314 *os << "format: " << std::setw(14) << GetFormatString(sdm_layer->input_buffer.format);
2315 *os << " dataspace:" << std::hex << "0x" << std::setw(8) << std::setfill('0')
2316 << client_target_->GetLayerDataspace() << std::dec << std::setfill(' ');
2317 *os << " buffer_id: " << std::hex << "0x" << sdm_layer->input_buffer.buffer_id << std::dec;
2318 *os << " secure: " << client_target_->IsProtected()
2319 << std::endl;
Gousemoodhin Nadafa08db9e2018-07-16 14:25:09 +05302320 }
2321
Saurabh Shahdccc0f42018-01-15 15:59:56 -08002322 if (layer_stack_invalid_) {
Dileep Marchya58928122020-01-28 12:16:51 +05302323 *os << "\n Layers added or removed but not reflected to SDM's layer stack yet\n";
2324 return;
Saurabh Shahdccc0f42018-01-15 15:59:56 -08002325 }
2326
Naseer Ahmed913502b2017-04-18 16:05:05 -04002327 if (color_mode_) {
Dileep Marchya58928122020-01-28 12:16:51 +05302328 *os << "\n----------Color Modes---------\n";
2329 color_mode_->Dump(os);
Naseer Ahmed913502b2017-04-18 16:05:05 -04002330 }
Saurabh Shah9c224a32017-11-09 12:17:44 -08002331
2332 if (display_intf_) {
Dileep Marchya58928122020-01-28 12:16:51 +05302333 *os << "\n------------SDM----------------\n";
2334 *os << display_intf_->Dump();
Saurabh Shah9c224a32017-11-09 12:17:44 -08002335 }
2336
Dileep Marchya58928122020-01-28 12:16:51 +05302337 *os << "\n";
Naseer Ahmed1fd59ea2016-05-05 13:59:23 -04002338}
Sushil Chauhan409e8442017-06-12 17:43:25 -07002339
2340bool HWCDisplay::CanSkipValidate() {
Sushil Chauhanca302b72018-02-27 18:38:22 -08002341 if (!validated_ || solid_fill_enable_) {
Naseer Ahmed34b341d2017-10-05 18:47:15 -04002342 return false;
2343 }
2344
Saurabh Dubey66b807e2018-05-11 10:05:07 +05302345 if ((tone_mapper_ && tone_mapper_->IsActive()) ||
Arun Kumar K.R2a419be2018-04-27 12:43:58 +05302346 layer_stack_.flags.single_buffered_layer_present) {
Saurabh Dubey66b807e2018-05-11 10:05:07 +05302347 DLOGV_IF(kTagClient, "Tonemapping enabled or single buffer layer present = %d"
2348 " Returning false.", layer_stack_.flags.single_buffered_layer_present);
Sushil Chauhan409e8442017-06-12 17:43:25 -07002349 return false;
2350 }
2351
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +05302352 if (client_target_->NeedsValidation()) {
Saurabh Dubeyd90a6a42017-10-24 16:28:01 +05302353 DLOGV_IF(kTagClient, "Framebuffer target needs validation. Returning false.");
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +05302354 return false;
2355 }
2356
Sushil Chauhan409e8442017-06-12 17:43:25 -07002357 for (auto hwc_layer : layer_set_) {
Ramkumar Radhakrishnan1a31bc22018-08-23 14:42:05 -07002358 Layer *layer = hwc_layer->GetSDMLayer();
Sushil Chauhan409e8442017-06-12 17:43:25 -07002359 if (hwc_layer->NeedsValidation()) {
Pullakavi Srinivasce3692b2020-02-13 01:14:09 +05302360 DLOGV_IF(kTagClient, "hwc_layer[%" PRIu64 "] needs validation. Returning false.",
Saurabh Dubeyd90a6a42017-10-24 16:28:01 +05302361 hwc_layer->GetId());
Sushil Chauhan409e8442017-06-12 17:43:25 -07002362 return false;
2363 }
2364
2365 // Do not allow Skip Validate, if any layer needs GPU Composition.
Ramkumar Radhakrishnan1a31bc22018-08-23 14:42:05 -07002366 if (layer->composition == kCompositionGPU || layer->composition == kCompositionNone) {
Pullakavi Srinivasce3692b2020-02-13 01:14:09 +05302367 DLOGV_IF(kTagClient, "hwc_layer[%" PRIu64 "] is %s. Returning false.", hwc_layer->GetId(),
Ramkumar Radhakrishnan1a31bc22018-08-23 14:42:05 -07002368 (layer->composition == kCompositionGPU) ? "GPU composed": "Dropped");
Sushil Chauhan409e8442017-06-12 17:43:25 -07002369 return false;
2370 }
2371 }
2372
Pullakavi Srinivasad8bd012019-04-22 17:04:51 +05302373 if (!layer_set_.empty() && !display_intf_->CanSkipValidate()) {
2374 return false;
2375 }
2376
Sushil Chauhan409e8442017-06-12 17:43:25 -07002377 return true;
2378}
2379
Sushil Chauhane3a9fd02017-10-12 18:00:05 -07002380HWC2::Error HWCDisplay::GetValidateDisplayOutput(uint32_t *out_num_types,
2381 uint32_t *out_num_requests) {
2382 *out_num_types = UINT32(layer_changes_.size());
2383 *out_num_requests = UINT32(layer_requests_.size());
2384
2385 return ((*out_num_types > 0) ? HWC2::Error::HasChanges : HWC2::Error::None);
2386}
2387
Varun Arora6ba9eda2019-02-07 17:59:32 -08002388HWC2::Error HWCDisplay::GetDisplayIdentificationData(uint8_t *out_port, uint32_t *out_data_size,
2389 uint8_t *out_data) {
2390 DisplayError ret = display_intf_->GetDisplayIdentificationData(out_port, out_data_size, out_data);
2391 if (ret != kErrorNone) {
Pullakavi Srinivasf2a31852019-04-23 14:32:08 -07002392 DLOGE("Failed due to SDM/Driver (err = %d, disp id = %" PRIu64
Varun Arora6ba9eda2019-02-07 17:59:32 -08002393 " %d-%d", ret, id_, sdm_id_, type_);
2394 }
Pullakavi Srinivasf2a31852019-04-23 14:32:08 -07002395
Varun Arora6ba9eda2019-02-07 17:59:32 -08002396 return HWC2::Error::None;
2397}
2398
Padmanabhan Komanduru13b5e102019-12-03 12:35:09 +05302399HWC2::Error HWCDisplay::SetDisplayElapseTime(uint64_t time) {
2400 elapse_timestamp_ = time;
2401 return HWC2::Error::None;
2402}
2403
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -07002404bool HWCDisplay::IsDisplayCommandMode() {
Tharaga Balachandran04192a62018-08-29 16:23:25 -04002405 return is_cmd_mode_;
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -07002406}
2407
Lakshmi Narayana Kalavala25fe12c2019-12-11 20:44:55 -08002408HWC2::Error HWCDisplay::SetDisplayedContentSamplingEnabledVndService(bool enabled) {
2409 return HWC2::Error::Unsupported;
2410}
2411
2412HWC2::Error HWCDisplay::SetDisplayedContentSamplingEnabled(int32_t enabled, uint8_t component_mask,
2413 uint64_t max_frames) {
2414 DLOGV("Request to start/stop histogram thread not supported on this display");
2415 return HWC2::Error::Unsupported;
2416}
2417
2418HWC2::Error HWCDisplay::GetDisplayedContentSamplingAttributes(int32_t *format, int32_t *dataspace,
2419 uint8_t *supported_components) {
2420 return HWC2::Error::Unsupported;
2421}
2422
2423HWC2::Error HWCDisplay::GetDisplayedContentSample(
2424 uint64_t max_frames, uint64_t timestamp, uint64_t *numFrames,
2425 int32_t samples_size[NUM_HISTOGRAM_COLOR_COMPONENTS],
2426 uint64_t *samples[NUM_HISTOGRAM_COLOR_COMPONENTS]) {
2427 return HWC2::Error::Unsupported;
2428}
2429
Sushil Chauhan36c059a2018-06-28 11:39:01 -07002430// Skip SDM prepare if all the layers in the current draw cycle are marked as Skip and
2431// previous draw cycle had GPU Composition, as the resources for GPU Target layer have
2432// already been validated and configured to the driver.
2433bool HWCDisplay::CanSkipSdmPrepare(uint32_t *num_types, uint32_t *num_requests) {
2434 if (!validated_ || layer_set_.empty()) {
2435 return false;
2436 }
2437
2438 bool skip_prepare = true;
2439 for (auto hwc_layer : layer_set_) {
2440 if (!hwc_layer->GetSDMLayer()->flags.skip ||
2441 (hwc_layer->GetDeviceSelectedCompositionType() != HWC2::Composition::Client)) {
2442 skip_prepare = false;
2443 layer_changes_.clear();
2444 break;
2445 }
2446 if (hwc_layer->GetClientRequestedCompositionType() != HWC2::Composition::Client) {
2447 layer_changes_[hwc_layer->GetId()] = HWC2::Composition::Client;
2448 }
2449 }
2450
2451 if (skip_prepare) {
2452 *num_types = UINT32(layer_changes_.size());
2453 *num_requests = 0;
2454 layer_stack_invalid_ = false;
2455 has_client_composition_ = true;
2456 client_target_->ResetValidation();
2457 validate_state_ = kNormalValidate;
2458 }
2459
2460 return skip_prepare;
2461}
2462
Pullakavi Srinivas3dbb0d92018-03-07 15:15:14 +05302463void HWCDisplay::UpdateRefreshRate() {
2464 for (auto hwc_layer : layer_set_) {
2465 if (hwc_layer->HasMetaDataRefreshRate()) {
2466 continue;
2467 }
2468 auto layer = hwc_layer->GetSDMLayer();
Mahesh Aiaf3a1f992019-01-16 13:07:42 -08002469 layer->frame_rate = std::min(current_refresh_rate_, HWCDisplay::GetThrottlingRefreshRate());
Pullakavi Srinivas3dbb0d92018-03-07 15:15:14 +05302470 }
2471}
2472
Arun Kumar K.R5b821552018-12-07 08:00:15 +05302473int32_t HWCDisplay::SetClientTargetDataSpace(int32_t dataspace) {
2474 if (client_target_->GetLayerDataspace() != dataspace) {
2475 client_target_->SetLayerDataspace(dataspace);
2476 Layer *sdm_layer = client_target_->GetSDMLayer();
2477 // Data space would be validated at GetClientTargetSupport, so just use here.
2478 sdm::GetSDMColorSpace(client_target_->GetLayerDataspace(),
2479 &sdm_layer->input_buffer.color_metadata);
2480 }
2481
2482 return 0;
2483}
2484
Rajavenu Kyathamaf26f402019-02-13 15:04:03 +05302485void HWCDisplay::WaitOnPreviousFence() {
2486 DisplayConfigFixedInfo display_config;
2487 display_intf_->GetConfig(&display_config);
2488 if (!display_config.is_cmdmode) {
2489 return;
2490 }
2491
2492 // Since prepare failed commit would follow the same.
2493 // Wait for previous rel fence.
2494 for (auto hwc_layer : layer_set_) {
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05302495 shared_ptr<Fence> fence = nullptr;
2496
2497 hwc_layer->PopBackReleaseFence(&fence);
2498 if (Fence::Wait(fence) != kErrorNone) {
2499 DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
2500 return;
Rajavenu Kyathamaf26f402019-02-13 15:04:03 +05302501 }
2502 hwc_layer->PushBackReleaseFence(fence);
2503 }
Rajavenu Kyatham9d509582019-02-13 15:29:55 +05302504
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05302505 if (Fence::Wait(fbt_release_fence_) != kErrorNone) {
2506 DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
2507 return;
Rajavenu Kyatham9d509582019-02-13 15:29:55 +05302508 }
Rajavenu Kyathamaf26f402019-02-13 15:04:03 +05302509}
2510
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +05302511void HWCDisplay::GetLayerStack(HWCLayerStack *stack) {
2512 stack->client_target = client_target_;
2513 stack->layer_map = layer_map_;
2514 stack->layer_set = layer_set_;
2515}
2516
2517void HWCDisplay::SetLayerStack(HWCLayerStack *stack) {
2518 client_target_ = stack->client_target;
2519 layer_map_ = stack->layer_map;
2520 layer_set_ = stack->layer_set;
2521}
2522
Padmanabhan Komanduruf5b7f992019-07-08 13:33:44 +05302523bool HWCDisplay::CheckResourceState() {
2524 if (display_intf_) {
2525 return display_intf_->CheckResourceState();
2526 }
2527
2528 return false;
2529}
2530
Pullakavi Srinivas81fee962019-07-26 15:49:32 +05302531void HWCDisplay::UpdateActiveConfig() {
2532 if (!pending_config_) {
2533 return;
2534 }
2535
2536 DisplayError error = display_intf_->SetActiveConfig(pending_config_index_);
2537 if (error != kErrorNone) {
2538 DLOGI("Failed to set %d config", INT(pending_config_index_));
Sushil Chauhan02e34162020-05-12 14:02:56 -07002539 } else {
2540 SetActiveConfigIndex(pending_config_index_);
Pullakavi Srinivas81fee962019-07-26 15:49:32 +05302541 }
2542
2543 // Reset pending config.
2544 pending_config_ = false;
2545}
2546
Sushil Chauhanf8541202020-02-03 23:14:36 -08002547int32_t HWCDisplay::GetDisplayConfigGroup(DisplayConfigGroupInfo variable_config) {
2548 for (auto &config : variable_config_map_) {
2549 DisplayConfigGroupInfo const &group_info = config.second;
2550 if (group_info == variable_config) {
2551 return INT32(config.first);
2552 }
2553 }
2554
2555 return -1;
2556}
2557
Sushil Chauhandbd8db42020-02-28 13:07:48 -08002558HWC2::Error HWCDisplay::GetDisplayVsyncPeriod(VsyncPeriodNanos *vsync_period) {
2559 if (GetTransientVsyncPeriod(vsync_period)) {
2560 return HWC2::Error::None;
2561 }
2562
2563 return GetVsyncPeriodByActiveConfig(vsync_period);
2564}
2565
2566HWC2::Error HWCDisplay::SetActiveConfigWithConstraints(
2567 hwc2_config_t config, const VsyncPeriodChangeConstraints *vsync_period_change_constraints,
2568 VsyncPeriodChangeTimeline *out_timeline) {
2569 if (variable_config_map_.find(config) == variable_config_map_.end()) {
2570 DLOGE("Invalid config: %d", config);
2571 return HWC2::Error::BadConfig;
2572 }
2573
2574 if (vsync_period_change_constraints->seamlessRequired && !AllowSeamless(config)) {
2575 DLOGE("Seamless switch to the config: %d, is not allowed!", config);
2576 return HWC2::Error::SeamlessNotAllowed;
2577 }
2578
2579 VsyncPeriodNanos vsync_period;
2580 if (GetDisplayVsyncPeriod(&vsync_period) != HWC2::Error::None) {
2581 return HWC2::Error::BadConfig;
2582 }
2583
2584 std::tie(out_timeline->refreshTimeNanos, out_timeline->newVsyncAppliedTimeNanos) =
2585 RequestActiveConfigChange(config, vsync_period,
2586 vsync_period_change_constraints->desiredTimeNanos);
2587
2588 out_timeline->refreshRequired = true;
2589 return HWC2::Error::None;
2590}
2591
2592void HWCDisplay::ProcessActiveConfigChange() {
2593 if (!IsActiveConfigReadyToSubmit(systemTime(SYSTEM_TIME_MONOTONIC))) {
2594 return;
2595 }
2596
2597 DTRACE_SCOPED();
2598 VsyncPeriodNanos vsync_period;
2599 if (GetVsyncPeriodByActiveConfig(&vsync_period) == HWC2::Error::None) {
2600 SubmitActiveConfigChange(vsync_period);
2601 }
2602}
2603
2604HWC2::Error HWCDisplay::GetVsyncPeriodByActiveConfig(VsyncPeriodNanos *vsync_period) {
2605 hwc2_config_t active_config;
2606
Sushil Chauhan02e34162020-05-12 14:02:56 -07002607 auto error = GetCachedActiveConfig(&active_config);
Sushil Chauhandbd8db42020-02-28 13:07:48 -08002608 if (error != HWC2::Error::None) {
2609 DLOGE("Failed to get active config!");
2610 return error;
2611 }
2612
2613 int32_t active_vsync_period;
2614 error = GetDisplayAttribute(active_config, HwcAttribute::VSYNC_PERIOD, &active_vsync_period);
2615 if (error != HWC2::Error::None) {
2616 DLOGE("Failed to get VsyncPeriod of config: %d", active_config);
2617 return error;
2618 }
2619
2620 *vsync_period = static_cast<VsyncPeriodNanos>(active_vsync_period);
2621 return HWC2::Error::None;
2622}
2623
2624bool HWCDisplay::GetTransientVsyncPeriod(VsyncPeriodNanos *vsync_period) {
2625 std::lock_guard<std::mutex> lock(transient_refresh_rate_lock_);
2626 auto now = systemTime(SYSTEM_TIME_MONOTONIC);
2627
2628 while (!transient_refresh_rate_info_.empty()) {
2629 if (IsActiveConfigApplied(now, transient_refresh_rate_info_.front().vsync_applied_time)) {
2630 transient_refresh_rate_info_.pop_front();
2631 } else {
2632 *vsync_period = transient_refresh_rate_info_.front().transient_vsync_period;
2633 return true;
2634 }
2635 }
2636
2637 return false;
2638}
2639
2640std::tuple<int64_t, int64_t> HWCDisplay::RequestActiveConfigChange(
2641 hwc2_config_t config, VsyncPeriodNanos current_vsync_period, int64_t desired_time) {
2642 int64_t refresh_time, applied_time;
2643 std::tie(refresh_time, applied_time) =
2644 EstimateVsyncPeriodChangeTimeline(current_vsync_period, desired_time);
2645
2646 pending_refresh_rate_config_ = config;
2647 pending_refresh_rate_refresh_time_ = refresh_time;
2648 pending_refresh_rate_applied_time_ = applied_time;
2649
2650 return std::make_tuple(refresh_time, applied_time);
2651}
2652
2653std::tuple<int64_t, int64_t> HWCDisplay::EstimateVsyncPeriodChangeTimeline(
2654 VsyncPeriodNanos current_vsync_period, int64_t desired_time) {
2655 const auto now = systemTime(SYSTEM_TIME_MONOTONIC);
2656 const auto delta = desired_time - now;
2657 const auto refresh_rate_activate_period = current_vsync_period * vsyncs_to_apply_rate_change_;
2658 nsecs_t refresh_time;
2659
2660 if (delta < 0) {
2661 refresh_time = now + (delta % current_vsync_period);
2662 } else if (delta < refresh_rate_activate_period) {
2663 refresh_time = now + (delta % current_vsync_period) - current_vsync_period;
2664 } else {
2665 refresh_time = desired_time - refresh_rate_activate_period;
2666 }
2667
2668 const auto applied_time = refresh_time + refresh_rate_activate_period;
2669 return std::make_tuple(refresh_time, applied_time);
2670}
2671
2672void HWCDisplay::SubmitActiveConfigChange(VsyncPeriodNanos current_vsync_period) {
Sushil Chauhan0c322e62020-03-20 17:42:52 -07002673 HWC2::Error error = SubmitDisplayConfig(pending_refresh_rate_config_);
Sushil Chauhandbd8db42020-02-28 13:07:48 -08002674 if (error != HWC2::Error::None) {
2675 return;
2676 }
2677
2678 std::lock_guard<std::mutex> lock(transient_refresh_rate_lock_);
2679 hwc_vsync_period_change_timeline_t timeline;
2680 std::tie(timeline.refreshTimeNanos, timeline.newVsyncAppliedTimeNanos) =
2681 EstimateVsyncPeriodChangeTimeline(current_vsync_period, pending_refresh_rate_refresh_time_);
2682
2683 transient_refresh_rate_info_.push_back({current_vsync_period, timeline.newVsyncAppliedTimeNanos});
2684 if (timeline.newVsyncAppliedTimeNanos != pending_refresh_rate_applied_time_) {
2685 timeline.refreshRequired = false;
2686 callbacks_->VsyncPeriodTimingChanged(id_, &timeline);
2687 }
2688
2689 pending_refresh_rate_config_ = UINT_MAX;
2690 pending_refresh_rate_refresh_time_ = INT64_MAX;
2691 pending_refresh_rate_applied_time_ = INT64_MAX;
2692}
2693
2694bool HWCDisplay::IsActiveConfigReadyToSubmit(int64_t time) {
2695 return ((pending_refresh_rate_config_ != UINT_MAX) &&
2696 IsTimeAfterOrEqualVsyncTime(time, pending_refresh_rate_refresh_time_));
2697}
2698
2699bool HWCDisplay::IsActiveConfigApplied(int64_t time, int64_t vsync_applied_time) {
2700 return IsTimeAfterOrEqualVsyncTime(time, vsync_applied_time);
2701}
2702
2703bool HWCDisplay::IsSameGroup(hwc2_config_t config_id1, hwc2_config_t config_id2) {
2704 const auto &variable_config1 = variable_config_map_.find(config_id1);
2705 const auto &variable_config2 = variable_config_map_.find(config_id2);
2706
2707 if ((variable_config1 == variable_config_map_.end()) ||
2708 (variable_config2 == variable_config_map_.end())) {
2709 DLOGE("Invalid config: %u, %u", config_id1, config_id2);
2710 return false;
2711 }
2712
2713 const DisplayConfigGroupInfo &config_group1 = variable_config1->second;
2714 const DisplayConfigGroupInfo &config_group2 = variable_config2->second;
2715
2716 return (config_group1 == config_group2);
2717}
2718
2719bool HWCDisplay::AllowSeamless(hwc2_config_t config) {
2720 hwc2_config_t active_config;
Sushil Chauhan02e34162020-05-12 14:02:56 -07002721 auto error = GetCachedActiveConfig(&active_config);
Sushil Chauhandbd8db42020-02-28 13:07:48 -08002722 if (error != HWC2::Error::None) {
2723 DLOGE("Failed to get active config!");
2724 return false;
2725 }
2726
2727 return IsSameGroup(active_config, config);
2728}
2729
Sushil Chauhan0c322e62020-03-20 17:42:52 -07002730HWC2::Error HWCDisplay::SubmitDisplayConfig(hwc2_config_t config) {
2731 DTRACE_SCOPED();
2732
2733 hwc2_config_t current_config = 0;
2734 GetActiveConfig(&current_config);
2735 if (current_config == config) {
2736 return HWC2::Error::None;
2737 }
2738
2739 DisplayError error = display_intf_->SetActiveConfig(config);
2740 if (error != kErrorNone) {
2741 DLOGE("Failed to set %d config! Error: %d", config, error);
2742 return HWC2::Error::BadConfig;
2743 }
2744
2745 validated_ = false;
Sushil Chauhan02e34162020-05-12 14:02:56 -07002746 SetActiveConfigIndex(config);
Sushil Chauhan0c322e62020-03-20 17:42:52 -07002747 DLOGI("Active configuration changed to: %d", config);
2748
2749 return HWC2::Error::None;
2750}
2751
Sushil Chauhan02e34162020-05-12 14:02:56 -07002752HWC2::Error HWCDisplay::GetCachedActiveConfig(hwc2_config_t *active_config) {
2753 int config_index = GetActiveConfigIndex();
2754 if ((config_index < 0) || (config_index >= hwc_config_map_.size())) {
2755 return GetActiveConfig(active_config);
2756 }
2757
2758 *active_config = static_cast<hwc2_config_t>(hwc_config_map_.at(config_index));
2759 return HWC2::Error::None;
2760}
2761
2762void HWCDisplay::SetActiveConfigIndex(int index) {
2763 std::lock_guard<std::mutex> lock(active_config_lock_);
2764 active_config_index_ = index;
2765}
2766
2767int HWCDisplay::GetActiveConfigIndex() {
2768 std::lock_guard<std::mutex> lock(active_config_lock_);
2769 return active_config_index_;
2770}
2771
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002772} // namespace sdm