blob: 5e04e307f38166326328cfe4d3bf9f49ec9ffa2b [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;
56
Arun Kumar K.R2a419be2018-04-27 12:43:58 +053057bool NeedsToneMap(const LayerStack &layer_stack) {
58 for (Layer *layer : layer_stack.layers) {
59 if (layer->request.flags.tone_map) {
60 return true;
61 }
62 }
63 return false;
64}
65
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070066HWCColorMode::HWCColorMode(DisplayInterface *display_intf) : display_intf_(display_intf) {}
67
68HWC2::Error HWCColorMode::Init() {
69 PopulateColorModes();
Qing Huang97b35442019-04-30 13:51:17 -070070 return HWC2::Error::None;
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070071}
72
73HWC2::Error HWCColorMode::DeInit() {
Naseer Ahmede7a77982018-06-04 10:56:04 -040074 color_mode_map_.clear();
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070075 return HWC2::Error::None;
76}
77
78uint32_t HWCColorMode::GetColorModeCount() {
Naseer Ahmede7a77982018-06-04 10:56:04 -040079 uint32_t count = UINT32(color_mode_map_.size());
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070080 DLOGI("Supported color mode count = %d", count);
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070081 return std::max(1U, count);
82}
83
Naseer Ahmede7a77982018-06-04 10:56:04 -040084uint32_t HWCColorMode::GetRenderIntentCount(ColorMode mode) {
85 uint32_t count = UINT32(color_mode_map_[mode].size());
86 DLOGI("mode: %d supported rendering intent count = %d", mode, count);
87 return std::max(1U, count);
88}
89
90HWC2::Error HWCColorMode::GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes) {
91 auto it = color_mode_map_.begin();
92 *out_num_modes = std::min(*out_num_modes, UINT32(color_mode_map_.size()));
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +053093 for (uint32_t i = 0; i < *out_num_modes; it++, i++) {
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070094 out_modes[i] = it->first;
Naseer Ahmede7a77982018-06-04 10:56:04 -040095 DLOGI("Color mode = %d is supported", out_modes[i]);
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070096 }
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070097 return HWC2::Error::None;
98}
99
Naseer Ahmede7a77982018-06-04 10:56:04 -0400100HWC2::Error HWCColorMode::GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
101 RenderIntent *out_intents) {
102 if (color_mode_map_.find(mode) == color_mode_map_.end()) {
103 return HWC2::Error::BadParameter;
104 }
105 auto it = color_mode_map_[mode].begin();
106 *out_num_intents = std::min(*out_num_intents, UINT32(color_mode_map_[mode].size()));
107 for (uint32_t i = 0; i < *out_num_intents; it++, i++) {
108 out_intents[i] = it->first;
109 DLOGI("Color mode = %d is supported with render intent = %d", mode, out_intents[i]);
110 }
111 return HWC2::Error::None;
112}
113
Sushil Chauhan8008d602018-09-04 14:43:27 -0700114HWC2::Error HWCColorMode::ValidateColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
Gousemoodhin Nadaf0e566872019-05-13 16:14:54 +0530115 if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_BT2020) {
Xu Yang47f44092019-02-13 14:09:53 +0800116 DLOGE("Invalid mode: %d", mode);
Naseer Ahmed7cb8f7a2017-05-12 16:33:57 -0400117 return HWC2::Error::BadParameter;
118 }
Naseer Ahmede7a77982018-06-04 10:56:04 -0400119 if (color_mode_map_.find(mode) == color_mode_map_.end()) {
Xu Yang47f44092019-02-13 14:09:53 +0800120 DLOGE("Could not find mode: %d", mode);
Naseer Ahmede7a77982018-06-04 10:56:04 -0400121 return HWC2::Error::Unsupported;
122 }
123 if (color_mode_map_[mode].find(intent) == color_mode_map_[mode].end()) {
Xu Yang47f44092019-02-13 14:09:53 +0800124 DLOGE("Could not find render intent %d in mode %d", intent, mode);
Arun Kumar K.R1018d5b2017-06-08 13:51:05 +0530125 return HWC2::Error::Unsupported;
126 }
127
Sushil Chauhan8008d602018-09-04 14:43:27 -0700128 return HWC2::Error::None;
129}
130
131HWC2::Error HWCColorMode::SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
132 DTRACE_SCOPED();
133 HWC2::Error hwc_error = ValidateColorModeWithRenderIntent(mode, intent);
134 if (hwc_error != HWC2::Error::None) {
135 return hwc_error;
136 }
137
138 if (current_color_mode_ == mode && current_render_intent_ == intent) {
139 return HWC2::Error::None;
140 }
141
Xu Yang84e61412018-12-06 14:52:16 +0800142 auto mode_string = color_mode_map_[mode][intent][kSdrType];
Sushil Chauhan8008d602018-09-04 14:43:27 -0700143 DisplayError error = display_intf_->SetColorMode(mode_string);
144 if (error != kErrorNone) {
145 DLOGE("failed for mode = %d intent = %d name = %s", mode, intent, mode_string.c_str());
146 return HWC2::Error::Unsupported;
147 }
148 // The mode does not have the PCC configured, restore the transform
149 RestoreColorTransform();
150
151 current_color_mode_ = mode;
152 current_render_intent_ = intent;
153 DLOGV_IF(kTagClient, "Successfully applied mode = %d intent = %d name = %s", mode, intent,
154 mode_string.c_str());
155 return HWC2::Error::None;
156}
157
158HWC2::Error HWCColorMode::CacheColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
159 HWC2::Error error = ValidateColorModeWithRenderIntent(mode, intent);
160 if (error != HWC2::Error::None) {
161 return error;
162 }
163
Naseer Ahmed6f8fefb2018-06-04 10:56:04 -0400164 if (current_color_mode_ == mode && current_render_intent_ == intent) {
165 return HWC2::Error::None;
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700166 }
167
Naseer Ahmede7a77982018-06-04 10:56:04 -0400168 current_color_mode_ = mode;
169 current_render_intent_ = intent;
Sushil Chauhan7cd110d2018-08-24 17:17:55 -0700170 apply_mode_ = true;
171
172 return HWC2::Error::None;
173}
174
Xu Yang84e61412018-12-06 14:52:16 +0800175HWC2::Error HWCColorMode::ApplyCurrentColorModeWithRenderIntent(bool hdr_present) {
Gousemoodhin Nadaf3adacfb2019-05-31 16:06:13 +0530176 // If panel does not support color modes, do not set color mode.
177 if (color_mode_map_.size() <= 1) {
178 return HWC2::Error::None;
179 }
Sushil Chauhan7cd110d2018-08-24 17:17:55 -0700180 if (!apply_mode_) {
Xu Yang84e61412018-12-06 14:52:16 +0800181 if ((hdr_present && curr_dynamic_range_ == kHdrType) ||
182 (!hdr_present && curr_dynamic_range_ == kSdrType))
183 return HWC2::Error::None;
Sushil Chauhan7cd110d2018-08-24 17:17:55 -0700184 }
185
186 apply_mode_ = false;
Xu Yang84e61412018-12-06 14:52:16 +0800187 curr_dynamic_range_ = (hdr_present)? kHdrType : kSdrType;
188
189 // select mode according to the blend space and dynamic range
190 std::string mode_string = preferred_mode_[current_color_mode_][curr_dynamic_range_];
191 if (mode_string.empty()) {
192 mode_string = color_mode_map_[current_color_mode_][current_render_intent_][curr_dynamic_range_];
Naseer Ahmed1d092ea2019-05-01 20:34:52 -0400193 if (mode_string.empty() && hdr_present) {
194 // Use the colorimetric HDR mode, if an HDR mode with the current render intent is not present
195 mode_string = color_mode_map_[current_color_mode_][RenderIntent::COLORIMETRIC][kHdrType];
196 }
Xu Yang84e61412018-12-06 14:52:16 +0800197 if (mode_string.empty() &&
Gousemoodhin Nadafd21743d2019-07-18 14:42:54 +0530198 (current_color_mode_ == ColorMode::DISPLAY_P3 ||
199 current_color_mode_ == ColorMode::DISPLAY_BT2020) &&
200 curr_dynamic_range_ == kHdrType) {
201 // fall back to display_p3/display_bt2020 SDR mode if there is no HDR mode
Xu Yang84e61412018-12-06 14:52:16 +0800202 mode_string = color_mode_map_[current_color_mode_][current_render_intent_][kSdrType];
203 }
Sushil Chauhan7cd110d2018-08-24 17:17:55 -0700204 }
205
Xu Yang84e61412018-12-06 14:52:16 +0800206 auto error = SetPreferredColorModeInternal(mode_string, false, NULL, NULL);
207 if (error == HWC2::Error::None) {
208 // The mode does not have the PCC configured, restore the transform
209 RestoreColorTransform();
210 DLOGV_IF(kTagClient, "Successfully applied mode = %d intent = %d range = %d name = %s",
211 current_color_mode_, current_render_intent_, curr_dynamic_range_, mode_string.c_str());
212 }
Sushil Chauhan7cd110d2018-08-24 17:17:55 -0700213
Xu Yang84e61412018-12-06 14:52:16 +0800214 return error;
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700215}
216
Naseer Ahmed6776dae2017-05-09 11:49:41 -0400217HWC2::Error HWCColorMode::SetColorModeById(int32_t color_mode_id) {
218 DLOGI("Applying mode: %d", color_mode_id);
219 DisplayError error = display_intf_->SetColorModeById(color_mode_id);
220 if (error != kErrorNone) {
Saurabh Dubeyd90a6a42017-10-24 16:28:01 +0530221 DLOGI_IF(kTagClient, "Failed to apply mode: %d", color_mode_id);
Naseer Ahmed6776dae2017-05-09 11:49:41 -0400222 return HWC2::Error::BadParameter;
223 }
224 return HWC2::Error::None;
225}
226
Xu Yang84e61412018-12-06 14:52:16 +0800227HWC2::Error HWCColorMode::SetPreferredColorModeInternal(const std::string &mode_string,
228 bool from_client, ColorMode *color_mode, DynamicRangeType *dynamic_range) {
229 DisplayError error = kErrorNone;
230 ColorMode mode = ColorMode::NATIVE;
231 DynamicRangeType range = kSdrType;
232
233 if (from_client) {
234 // get blend space and dynamic range of the mode
235 AttrVal attr;
236 std::string color_gamut_string, dynamic_range_string;
237 error = display_intf_->GetColorModeAttr(mode_string, &attr);
238 if (error) {
239 DLOGE("Failed to get mode attributes for mode %d", mode_string.c_str());
240 return HWC2::Error::BadParameter;
241 }
242
243 if (!attr.empty()) {
244 for (auto &it : attr) {
245 if (it.first.find(kColorGamutAttribute) != std::string::npos) {
246 color_gamut_string = it.second;
247 } else if (it.first.find(kDynamicRangeAttribute) != std::string::npos) {
248 dynamic_range_string = it.second;
249 }
250 }
251 }
252
253 if (color_gamut_string.empty() || dynamic_range_string.empty()) {
254 DLOGE("Invalid attributes for mode %s: color_gamut = %s, dynamic_range = %s",
255 mode_string.c_str(), color_gamut_string.c_str(), dynamic_range_string.c_str());
256 return HWC2::Error::BadParameter;
257 }
258
259 if (color_gamut_string == kDcip3) {
260 mode = ColorMode::DISPLAY_P3;
261 } else if (color_gamut_string == kSrgb) {
262 mode = ColorMode::SRGB;
263 }
264 if (dynamic_range_string == kHdr) {
265 range = kHdrType;
266 }
267
268 if (color_mode) {
269 *color_mode = mode;
270 }
271 if (dynamic_range) {
272 *dynamic_range = range;
273 }
274 }
275
276 // apply the mode from client if it matches
277 // the current blend space and dynamic range,
278 // skip the check for the mode from SF.
279 if ((!from_client) || (current_color_mode_ == mode && curr_dynamic_range_ == range)) {
280 DLOGI("Applying mode: %s", mode_string.c_str());
281 error = display_intf_->SetColorMode(mode_string);
282 if (error != kErrorNone) {
283 DLOGE("Failed to apply mode: %s", mode_string.c_str());
284 return HWC2::Error::BadParameter;
285 }
286 }
287
288 return HWC2::Error::None;
289}
290
291HWC2::Error HWCColorMode::SetColorModeFromClientApi(std::string mode_string) {
292 ColorMode mode = ColorMode::NATIVE;
293 DynamicRangeType range = kSdrType;
294
295 auto error = SetPreferredColorModeInternal(mode_string, true, &mode, &range);
296 if (error == HWC2::Error::None) {
297 preferred_mode_[mode][range] = mode_string;
298 DLOGV_IF(kTagClient, "Put mode %s(mode %d, range %d) into preferred_mode",
299 mode_string.c_str(), mode, range);
300 }
301
302 return error;
303}
304
Ch Ganesh Kumar5d43ff62017-10-13 19:01:47 +0530305HWC2::Error HWCColorMode::RestoreColorTransform() {
306 DisplayError error = display_intf_->SetColorTransform(kColorTransformMatrixCount, color_matrix_);
307 if (error != kErrorNone) {
308 DLOGE("Failed to set Color Transform");
309 return HWC2::Error::BadParameter;
310 }
311
312 return HWC2::Error::None;
313}
314
Naseer Ahmede7a77982018-06-04 10:56:04 -0400315HWC2::Error HWCColorMode::SetColorTransform(const float *matrix,
316 android_color_transform_t /*hint*/) {
Naseer Ahmedf5187022017-07-24 16:15:28 -0400317 DTRACE_SCOPED();
Naseer Ahmede7a77982018-06-04 10:56:04 -0400318 auto status = HWC2::Error::None;
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700319 double color_matrix[kColorTransformMatrixCount] = {0};
320 CopyColorTransformMatrix(matrix, color_matrix);
321
Naseer Ahmede7a77982018-06-04 10:56:04 -0400322 DisplayError error = display_intf_->SetColorTransform(kColorTransformMatrixCount, color_matrix);
323 if (error != kErrorNone) {
324 DLOGE("Failed to set Color Transform Matrix");
325 status = HWC2::Error::Unsupported;
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700326 }
Naseer Ahmede7a77982018-06-04 10:56:04 -0400327 CopyColorTransformMatrix(matrix, color_matrix_);
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700328 return status;
329}
330
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700331void HWCColorMode::PopulateColorModes() {
332 uint32_t color_mode_count = 0;
Naseer Ahmede7a77982018-06-04 10:56:04 -0400333 // SDM returns modes which have attributes defining mode and rendering intent
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700334 DisplayError error = display_intf_->GetColorModeCount(&color_mode_count);
335 if (error != kErrorNone || (color_mode_count == 0)) {
336 DLOGW("GetColorModeCount failed, use native color mode");
Xu Yang84e61412018-12-06 14:52:16 +0800337 color_mode_map_[ColorMode::NATIVE][RenderIntent::COLORIMETRIC]
338 [kSdrType] = "hal_native_identity";
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700339 return;
340 }
341
Saurabh Dubeyd90a6a42017-10-24 16:28:01 +0530342 DLOGV_IF(kTagClient, "Color Modes supported count = %d", color_mode_count);
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700343
344 std::vector<std::string> color_modes(color_mode_count);
345 error = display_intf_->GetColorModes(&color_mode_count, &color_modes);
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700346 for (uint32_t i = 0; i < color_mode_count; i++) {
347 std::string &mode_string = color_modes.at(i);
Saurabh Dubeyd90a6a42017-10-24 16:28:01 +0530348 DLOGV_IF(kTagClient, "Color Mode[%d] = %s", i, mode_string.c_str());
Qing Huang3f21afb2017-04-19 15:11:49 +0800349 AttrVal attr;
350 error = display_intf_->GetColorModeAttr(mode_string, &attr);
Gousemoodhin Nadaf56186602018-06-03 15:23:10 +0530351 std::string color_gamut = kNative, dynamic_range = kSdr, pic_quality = kStandard, transfer;
Xu Yang47f44092019-02-13 14:09:53 +0800352 int int_render_intent = -1;
Qing Huang3f21afb2017-04-19 15:11:49 +0800353 if (!attr.empty()) {
Qing Huang3f21afb2017-04-19 15:11:49 +0800354 for (auto &it : attr) {
355 if (it.first.find(kColorGamutAttribute) != std::string::npos) {
356 color_gamut = it.second;
357 } else if (it.first.find(kDynamicRangeAttribute) != std::string::npos) {
358 dynamic_range = it.second;
359 } else if (it.first.find(kPictureQualityAttribute) != std::string::npos) {
360 pic_quality = it.second;
Gousemoodhin Nadaf56186602018-06-03 15:23:10 +0530361 } else if (it.first.find(kGammaTransferAttribute) != std::string::npos) {
362 transfer = it.second;
Xu Yang47f44092019-02-13 14:09:53 +0800363 } else if (it.first.find(kRenderIntentAttribute) != std::string::npos) {
364 int_render_intent = std::stoi(it.second);
Qing Huang3f21afb2017-04-19 15:11:49 +0800365 }
366 }
Saurabh Dubeyd90a6a42017-10-24 16:28:01 +0530367
Xu Yang47f44092019-02-13 14:09:53 +0800368 if (int_render_intent < 0 || int_render_intent > MAX_EXTENDED_RENDER_INTENT) {
369 DLOGW("Invalid render intent %d for mode %s", int_render_intent, mode_string.c_str());
370 continue;
371 }
372 DLOGV_IF(kTagClient, "color_gamut : %s, dynamic_range : %s, pic_quality : %s, "
373 "render_intent : %d", color_gamut.c_str(), dynamic_range.c_str(),
374 pic_quality.c_str(), int_render_intent);
375
376 auto render_intent = static_cast<RenderIntent>(int_render_intent);
Naseer Ahmede7a77982018-06-04 10:56:04 -0400377 if (color_gamut == kNative) {
Xu Yang47f44092019-02-13 14:09:53 +0800378 color_mode_map_[ColorMode::NATIVE][render_intent][kSdrType] = mode_string;
Qing Huang3f21afb2017-04-19 15:11:49 +0800379 }
Naseer Ahmed0c689d42017-05-15 17:14:48 -0400380
Naseer Ahmede7a77982018-06-04 10:56:04 -0400381 if (color_gamut == kSrgb && dynamic_range == kSdr) {
Xu Yang47f44092019-02-13 14:09:53 +0800382 color_mode_map_[ColorMode::SRGB][render_intent][kSdrType] = mode_string;
Naseer Ahmede7a77982018-06-04 10:56:04 -0400383 }
384
385 if (color_gamut == kDcip3 && dynamic_range == kSdr) {
Xu Yang47f44092019-02-13 14:09:53 +0800386 color_mode_map_[ColorMode::DISPLAY_P3][render_intent][kSdrType] = mode_string;
Naseer Ahmede7a77982018-06-04 10:56:04 -0400387 }
Xu Yang47f44092019-02-13 14:09:53 +0800388 if (color_gamut == kDcip3 && dynamic_range == kHdr) {
Xu Yang84e61412018-12-06 14:52:16 +0800389 if (display_intf_->IsSupportSsppTonemap()) {
Xu Yang47f44092019-02-13 14:09:53 +0800390 color_mode_map_[ColorMode::DISPLAY_P3][render_intent][kHdrType] = mode_string;
391 } else if (pic_quality == kStandard) {
Qing Huang6d31af62019-08-12 13:42:41 +0800392 color_mode_map_[ColorMode::BT2100_PQ][render_intent]
Xu Yang84e61412018-12-06 14:52:16 +0800393 [kHdrType] = mode_string;
Qing Huang6d31af62019-08-12 13:42:41 +0800394 color_mode_map_[ColorMode::BT2100_HLG][render_intent]
Xu Yang84e61412018-12-06 14:52:16 +0800395 [kHdrType] = mode_string;
396 }
Gousemoodhin Nadaf56186602018-06-03 15:23:10 +0530397 } else if (color_gamut == kBt2020) {
398 if (transfer == kSt2084) {
Xu Yang84e61412018-12-06 14:52:16 +0800399 color_mode_map_[ColorMode::BT2100_PQ][RenderIntent::COLORIMETRIC]
400 [kHdrType] = mode_string;
Gousemoodhin Nadaf56186602018-06-03 15:23:10 +0530401 } else if (transfer == kHlg) {
Xu Yang84e61412018-12-06 14:52:16 +0800402 color_mode_map_[ColorMode::BT2100_HLG][RenderIntent::COLORIMETRIC]
403 [kHdrType] = mode_string;
Gousemoodhin Nadaf0e566872019-05-13 16:14:54 +0530404 } else if (transfer == kSrgb) {
405 color_mode_map_[ColorMode::DISPLAY_BT2020][RenderIntent::COLORIMETRIC]
406 [kSdrType] = mode_string;
Gousemoodhin Nadaf56186602018-06-03 15:23:10 +0530407 }
Naseer Ahmede7a77982018-06-04 10:56:04 -0400408 }
409 } else {
410 // Look at the mode names, if no attributes are found
Qing Huang3f21afb2017-04-19 15:11:49 +0800411 if (mode_string.find("hal_native") != std::string::npos) {
Xu Yang84e61412018-12-06 14:52:16 +0800412 color_mode_map_[ColorMode::NATIVE][RenderIntent::COLORIMETRIC]
413 [kSdrType] = mode_string;
Qing Huang3f21afb2017-04-19 15:11:49 +0800414 }
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700415 }
416 }
417}
418
Naseer Ahmed913502b2017-04-18 16:05:05 -0400419void HWCColorMode::Dump(std::ostringstream* os) {
Naseer Ahmede7a77982018-06-04 10:56:04 -0400420 *os << "color modes supported: \n";
421 for (auto it : color_mode_map_) {
422 *os << "mode: " << static_cast<int32_t>(it.first) << " RIs { ";
Xu Yang84e61412018-12-06 14:52:16 +0800423 for (auto render_intent_it : color_mode_map_[it.first]) {
424 *os << static_cast<int32_t>(render_intent_it.first) << " dynamic_range [ ";
425 for (auto range_it : color_mode_map_[it.first][render_intent_it.first]) {
426 *os << static_cast<int32_t>(range_it.first) << " ";
427 }
428 *os << "] ";
Naseer Ahmede7a77982018-06-04 10:56:04 -0400429 }
430 *os << "} \n";
Naseer Ahmed913502b2017-04-18 16:05:05 -0400431 }
Naseer Ahmede7a77982018-06-04 10:56:04 -0400432 *os << "current mode: " << static_cast<uint32_t>(current_color_mode_) << std::endl;
433 *os << "current render_intent: " << static_cast<uint32_t>(current_render_intent_) << std::endl;
Xu Yang84e61412018-12-06 14:52:16 +0800434 if (curr_dynamic_range_ == kHdrType) {
435 *os << "current dynamic_range: HDR" << std::endl;
436 } else {
437 *os << "current dynamic_range: SDR" << std::endl;
438 }
Naseer Ahmed913502b2017-04-18 16:05:05 -0400439 *os << "current transform: ";
440 for (uint32_t i = 0; i < kColorTransformMatrixCount; i++) {
441 if (i % 4 == 0) {
442 *os << std::endl;
443 }
444 *os << std::fixed << std::setprecision(2) << std::setw(6) << std::setfill(' ')
445 << color_matrix_[i] << " ";
446 }
447 *os << std::endl;
448}
449
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530450HWCDisplay::HWCDisplay(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
451 HWCCallbacks *callbacks, HWCDisplayEventHandler* event_handler,
452 qService::QService *qservice, DisplayType type, hwc2_display_t id,
Gousemoodhin Nadaf087c3102019-01-07 19:34:56 +0530453 int32_t sdm_id, DisplayClass display_class)
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500454 : core_intf_(core_intf),
455 callbacks_(callbacks),
Varun Arora7c8ee542018-05-01 20:58:16 -0700456 event_handler_(event_handler),
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500457 type_(type),
458 id_(id),
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530459 sdm_id_(sdm_id),
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500460 qservice_(qservice),
461 display_class_(display_class) {
Naseer Ahmedd1830402017-03-01 18:38:12 -0500462 buffer_allocator_ = static_cast<HWCBufferAllocator *>(buffer_allocator);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500463}
464
465int HWCDisplay::Init() {
Varun Arora465c1f72018-02-08 16:18:50 -0800466 DisplayError error = kErrorNone;
467
Uday Kiran Pichika5e656b22018-05-15 18:48:24 +0530468 HWCDebugHandler::Get()->GetProperty(ENABLE_NULL_DISPLAY_PROP, &null_display_mode_);
Rajavenu Kyatham50966d82019-08-06 18:02:36 +0530469 HWCDebugHandler::Get()->GetProperty(ENABLE_ASYNC_POWERMODE, &async_power_mode_);
Varun Arora465c1f72018-02-08 16:18:50 -0800470
471 if (null_display_mode_) {
472 DisplayNull *disp_null = new DisplayNull();
473 disp_null->Init();
474 use_metadata_refresh_rate_ = false;
475 display_intf_ = disp_null;
Dileep Marchya4cb86b42018-05-01 19:34:51 +0530476 DLOGI("Enabling null display mode for display type %d", type_);
Varun Arora465c1f72018-02-08 16:18:50 -0800477 } else {
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530478 error = core_intf_->CreateDisplay(sdm_id_, this, &display_intf_);
Varun Arora465c1f72018-02-08 16:18:50 -0800479 if (error != kErrorNone) {
Mathew Joseph Karimpanal23e2da02018-11-13 17:44:43 +0530480 if (kErrorDeviceRemoved == error) {
481 DLOGW("Display creation cancelled. Display %d-%d removed.", sdm_id_, type_);
482 return -ENODEV;
483 } else {
484 DLOGE("Display create failed. Error = %d display_id = %d event_handler = %p disp_intf = %p",
485 error, sdm_id_, this, &display_intf_);
486 return -EINVAL;
487 }
Varun Arora465c1f72018-02-08 16:18:50 -0800488 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500489 }
490
Saurabh Shaha307e8c2017-09-28 18:05:40 -0700491 validated_ = false;
Uday Kiran Pichika5e656b22018-05-15 18:48:24 +0530492 HWCDebugHandler::Get()->GetProperty(DISABLE_HDR, &disable_hdr_handling_);
Arun Kumar K.R2be0bf82017-05-24 15:14:41 +0530493 if (disable_hdr_handling_) {
494 DLOGI("HDR Handling disabled");
495 }
496
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500497 int property_swap_interval = 1;
Uday Kiran Pichika2febe6f2018-05-22 19:23:32 +0530498 HWCDebugHandler::Get()->GetProperty(ZERO_SWAP_INTERVAL, &property_swap_interval);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500499 if (property_swap_interval == 0) {
500 swap_interval_zero_ = true;
501 }
502
Naseer Ahmed42752212017-01-27 17:32:21 -0500503 client_target_ = new HWCLayer(id_, buffer_allocator_);
504
Rajavenu Kyatham40fc5382017-07-12 18:36:55 +0530505 error = display_intf_->GetNumVariableInfoConfigs(&num_configs_);
506 if (error != kErrorNone) {
507 DLOGE("Getting config count failed. Error = %d", error);
508 return -EINVAL;
509 }
510
Pullakavi Srinivas9189e602018-12-19 16:58:07 +0530511 UpdateConfigs();
512
Arun Kumar K.R51be3d12017-03-31 19:54:38 -0700513 tone_mapper_ = new HWCToneMapper(buffer_allocator_);
514
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500515 display_intf_->GetRefreshRateRange(&min_refresh_rate_, &max_refresh_rate_);
516 current_refresh_rate_ = max_refresh_rate_;
Sushil Chauhan409e8442017-06-12 17:43:25 -0700517
518 GetUnderScanConfig();
Sushil Chauhan9735cf82018-07-10 12:06:01 -0700519
520 DisplayConfigFixedInfo fixed_info = {};
521 display_intf_->GetConfig(&fixed_info);
Tharaga Balachandran04192a62018-08-29 16:23:25 -0400522 is_cmd_mode_ = fixed_info.is_cmdmode;
Pullakavi Srinivas984e7032018-10-08 14:52:15 +0530523 partial_update_enabled_ = fixed_info.partial_update || (!fixed_info.is_cmdmode);
Sushil Chauhan9735cf82018-07-10 12:06:01 -0700524 client_target_->SetPartialUpdate(partial_update_enabled_);
525
Sushil Chauhan7bd20662018-08-20 17:51:32 -0700526 int disable_fast_path = 0;
527 HWCDebugHandler::Get()->GetProperty(DISABLE_FAST_PATH, &disable_fast_path);
528 fast_path_enabled_ = !(disable_fast_path == 1);
529
Xu Yang7469c4f2019-11-27 10:25:59 +0800530 game_supported_ = display_intf_->GameEnhanceSupported();
531
532 DLOGI("Display created with id: %d, game_supported_: %d", id_, game_supported_);
Rajavenu Kyatham40fc5382017-07-12 18:36:55 +0530533
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500534 return 0;
535}
536
Pullakavi Srinivas9189e602018-12-19 16:58:07 +0530537void HWCDisplay::UpdateConfigs() {
538 // SF doesnt care about dynamic bit clk support.
539 // Exposing all configs will result in getting/setting of redundant configs.
540
541 // For each config store the corresponding index which client understands.
542 hwc_config_map_.resize(num_configs_);
543
544 for (uint32_t i = 0; i < num_configs_; i++) {
545 DisplayConfigVariableInfo info = {};
546 GetDisplayAttributesForConfig(INT(i), &info);
547 bool config_exists = false;
548 for (auto &config : variable_config_map_) {
549 if (config.second == info) {
550 config_exists = true;
551 hwc_config_map_.at(i) = config.first;
552 break;
553 }
554 }
555
556 if (!config_exists) {
557 variable_config_map_[i] = info;
558 hwc_config_map_.at(i) = i;
559 }
560 }
561
562 // Update num config count.
563 num_configs_ = UINT32(variable_config_map_.size());
564 DLOGI("num_configs = %d", num_configs_);
565}
566
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500567int HWCDisplay::Deinit() {
Varun Arora465c1f72018-02-08 16:18:50 -0800568 if (null_display_mode_) {
569 delete static_cast<DisplayNull *>(display_intf_);
570 display_intf_ = nullptr;
571 } else {
572 DisplayError error = core_intf_->DestroyDisplay(display_intf_);
573 if (error != kErrorNone) {
574 DLOGE("Display destroy failed. Error = %d", error);
575 return -EINVAL;
576 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500577 }
578
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500579 delete client_target_;
Prabhanjan Kandula2e8fba82017-11-13 11:47:10 -0800580 for (auto hwc_layer : layer_set_) {
581 delete hwc_layer;
582 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500583
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700584 if (color_mode_) {
585 color_mode_->DeInit();
586 delete color_mode_;
587 }
588
Varun Arora465c1f72018-02-08 16:18:50 -0800589 if (tone_mapper_) {
590 delete tone_mapper_;
591 tone_mapper_ = nullptr;
592 }
Arun Kumar K.R51be3d12017-03-31 19:54:38 -0700593
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500594 return 0;
595}
596
597// LayerStack operations
598HWC2::Error HWCDisplay::CreateLayer(hwc2_layer_t *out_layer_id) {
Naseer Ahmed42752212017-01-27 17:32:21 -0500599 HWCLayer *layer = *layer_set_.emplace(new HWCLayer(id_, buffer_allocator_));
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500600 layer_map_.emplace(std::make_pair(layer->GetId(), layer));
601 *out_layer_id = layer->GetId();
Naseer Ahmed72dea242016-05-03 19:13:07 -0400602 geometry_changes_ |= GeometryChanges::kAdded;
Saurabh Shaha307e8c2017-09-28 18:05:40 -0700603 validated_ = false;
Saurabh Shahdccc0f42018-01-15 15:59:56 -0800604 layer_stack_invalid_ = true;
Sushil Chauhan9735cf82018-07-10 12:06:01 -0700605 layer->SetPartialUpdate(partial_update_enabled_);
Saurabh Shahdccc0f42018-01-15 15:59:56 -0800606
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500607 return HWC2::Error::None;
608}
609
610HWCLayer *HWCDisplay::GetHWCLayer(hwc2_layer_t layer_id) {
611 const auto map_layer = layer_map_.find(layer_id);
612 if (map_layer == layer_map_.end()) {
Dileep Marchya9e388172019-09-12 11:44:19 +0530613 DLOGW("[%" PRIu64 "] GetLayer(%" PRIu64 ") failed: no such layer", id_, layer_id);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500614 return nullptr;
615 } else {
616 return map_layer->second;
617 }
618}
619
620HWC2::Error HWCDisplay::DestroyLayer(hwc2_layer_t layer_id) {
621 const auto map_layer = layer_map_.find(layer_id);
622 if (map_layer == layer_map_.end()) {
Dileep Marchya9e388172019-09-12 11:44:19 +0530623 DLOGW("[%" PRIu64 "] destroyLayer(%" PRIu64 ") failed: no such layer", id_, layer_id);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500624 return HWC2::Error::BadLayer;
625 }
626 const auto layer = map_layer->second;
627 layer_map_.erase(map_layer);
628 const auto z_range = layer_set_.equal_range(layer);
629 for (auto current = z_range.first; current != z_range.second; ++current) {
630 if (*current == layer) {
631 current = layer_set_.erase(current);
Naseer Ahmede95fe3f2016-06-23 16:56:24 -0400632 delete layer;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500633 break;
634 }
635 }
636
Naseer Ahmed72dea242016-05-03 19:13:07 -0400637 geometry_changes_ |= GeometryChanges::kRemoved;
Saurabh Shaha307e8c2017-09-28 18:05:40 -0700638 validated_ = false;
Saurabh Shahdccc0f42018-01-15 15:59:56 -0800639 layer_stack_invalid_ = true;
640
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500641 return HWC2::Error::None;
642}
643
Naseer Ahmedade4ee62016-10-07 17:07:38 -0400644
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500645void HWCDisplay::BuildLayerStack() {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500646 layer_stack_ = LayerStack();
647 display_rect_ = LayerRect();
648 metadata_refresh_rate_ = 0;
Naseer Ahmeda699e792017-11-09 15:08:31 -0500649 layer_stack_.flags.animating = animating_;
Sushil Chauhan7bd20662018-08-20 17:51:32 -0700650 layer_stack_.flags.fast_path = fast_path_enabled_ && fast_path_composition_;
Gurpreet Singh Dhamia4276882019-04-12 10:30:58 -0700651
652 DTRACE_SCOPED();
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500653 // Add one layer for fb target
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500654 for (auto hwc_layer : layer_set_) {
Prabhanjan Kandula5265b052017-05-30 17:13:40 -0700655 // Reset layer data which SDM may change
656 hwc_layer->ResetPerFrameData();
657
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500658 Layer *layer = hwc_layer->GetSDMLayer();
Naseer Ahmed63c2b5d2016-08-25 16:54:41 -0400659 layer->flags = {}; // Reset earlier flags
Rajavenu Kyatham429c7872018-12-21 15:24:17 +0530660 // Mark all layers to skip, when client target handle is NULL
661 if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::Client ||
662 !client_target_->GetSDMLayer()->input_buffer.buffer_id) {
Naseer Ahmed63c2b5d2016-08-25 16:54:41 -0400663 layer->flags.skip = true;
664 } else if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::SolidColor) {
665 layer->flags.solid_fill = true;
666 }
667
Saurabh Dubey66b807e2018-05-11 10:05:07 +0530668 if (!hwc_layer->IsDataSpaceSupported()) {
Arun Kumar K.R961a28f2017-07-07 15:26:30 +0530669 layer->flags.skip = true;
Arun Kumar K.R961a28f2017-07-07 15:26:30 +0530670 }
Naseer Ahmedade4ee62016-10-07 17:07:38 -0400671
Arun Kumar K.R2c0ff8d2016-06-01 16:56:52 -0700672 // set default composition as GPU for SDM
673 layer->composition = kCompositionGPU;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500674
675 if (swap_interval_zero_) {
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +0530676 layer->input_buffer.acquire_fence = nullptr;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500677 }
678
Pullakavi Srinivase08594d2017-12-28 12:46:02 +0530679 bool is_secure = false;
Naseer Ahmed08add602018-07-18 14:55:00 -0400680 bool is_video = false;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500681 const private_handle_t *handle =
Arun Kumar K.R9c19cdd2016-11-21 16:48:43 -0800682 reinterpret_cast<const private_handle_t *>(layer->input_buffer.buffer_id);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500683 if (handle) {
Naseer Ahmed42752212017-01-27 17:32:21 -0500684 if (handle->buffer_type == BUFFER_TYPE_VIDEO) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500685 layer_stack_.flags.video_present = true;
Naseer Ahmed08add602018-07-18 14:55:00 -0400686 is_video = true;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500687 }
688 // TZ Protected Buffer - L1
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500689 // Gralloc Usage Protected Buffer - L3 - which needs to be treated as Secure & avoid fallback
Pullakavi Srinivase08594d2017-12-28 12:46:02 +0530690 if (handle->flags & private_handle_t::PRIV_FLAGS_PROTECTED_BUFFER ||
691 handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500692 layer_stack_.flags.secure_present = true;
Pullakavi Srinivase08594d2017-12-28 12:46:02 +0530693 is_secure = true;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500694 }
Gousemoodhin Nadaf2db55342018-08-10 15:52:34 +0530695 // UBWC PI format
696 if (handle->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED_PI) {
697 layer->input_buffer.flags.ubwc_pi = true;
698 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500699 }
700
Pullakavi Srinivase08594d2017-12-28 12:46:02 +0530701 if (layer->input_buffer.flags.secure_display) {
Ramkumar Radhakrishnan4f6ded32019-06-11 15:44:48 -0700702 layer_stack_.flags.secure_present = true;
Pullakavi Srinivase08594d2017-12-28 12:46:02 +0530703 is_secure = true;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500704 }
705
Ramakant Singhae057092017-08-31 12:34:54 +0530706 if (hwc_layer->IsSingleBuffered() &&
707 !(hwc_layer->IsRotationPresent() || hwc_layer->IsScalingPresent())) {
708 layer->flags.single_buffer = true;
709 layer_stack_.flags.single_buffered_layer_present = true;
710 }
711
Arun Kumar K.R2be0bf82017-05-24 15:14:41 +0530712 bool hdr_layer = layer->input_buffer.color_metadata.colorPrimaries == ColorPrimaries_BT2020 &&
713 (layer->input_buffer.color_metadata.transfer == Transfer_SMPTE_ST2084 ||
714 layer->input_buffer.color_metadata.transfer == Transfer_HLG);
Arun Kumar K.R953fba62018-11-15 15:56:32 +0530715 if (hdr_layer && !disable_hdr_handling_) {
Gousemoodhin Nadaf839f29d2018-06-04 10:56:04 -0400716 // Dont honor HDR when its handling is disabled
Arun Kumar K.R51be3d12017-03-31 19:54:38 -0700717 layer->input_buffer.flags.hdr = true;
718 layer_stack_.flags.hdr_present = true;
719 }
720
Pullakavi Srinivasc6a110e2018-04-19 20:32:13 +0530721 if (hwc_layer->IsNonIntegralSourceCrop() && !is_secure && !hdr_layer &&
Naseer Ahmed08add602018-07-18 14:55:00 -0400722 !layer->flags.single_buffer && !layer->flags.solid_fill && !is_video) {
Pullakavi Srinivase08594d2017-12-28 12:46:02 +0530723 layer->flags.skip = true;
724 }
725
Pullakavi Srinivasf33ee312019-05-10 17:18:19 +0530726 if (!layer->flags.skip &&
727 (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::Cursor)) {
728 // Currently we support only one HWCursor & only at top most z-order
729 if ((*layer_set_.rbegin())->GetId() == hwc_layer->GetId()) {
730 layer->flags.cursor = true;
731 layer_stack_.flags.cursor_present = true;
732 }
733 }
734
Pullakavi Srinivase08594d2017-12-28 12:46:02 +0530735 if (layer->flags.skip) {
736 layer_stack_.flags.skip_present = true;
737 }
738
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500739 // TODO(user): Move to a getter if this is needed at other places
740 hwc_rect_t scaled_display_frame = {INT(layer->dst_rect.left), INT(layer->dst_rect.top),
741 INT(layer->dst_rect.right), INT(layer->dst_rect.bottom)};
Ramakant Singh830e9852017-07-29 21:31:09 +0530742 if (hwc_layer->GetGeometryChanges() & kDisplayFrame) {
743 ApplyScanAdjustment(&scaled_display_frame);
744 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500745 hwc_layer->SetLayerDisplayFrame(scaled_display_frame);
Ramakant Singh830e9852017-07-29 21:31:09 +0530746 hwc_layer->ResetPerFrameData();
Naseer Ahmed16c72b92016-07-22 20:02:31 -0400747 // SDM requires these details even for solid fill
748 if (layer->flags.solid_fill) {
Arun Kumar K.R9c19cdd2016-11-21 16:48:43 -0800749 LayerBuffer *layer_buffer = &layer->input_buffer;
Naseer Ahmed16c72b92016-07-22 20:02:31 -0400750 layer_buffer->width = UINT32(layer->dst_rect.right - layer->dst_rect.left);
751 layer_buffer->height = UINT32(layer->dst_rect.bottom - layer->dst_rect.top);
Naseer Ahmedebf4a0d2016-11-16 16:24:13 -0500752 layer_buffer->unaligned_width = layer_buffer->width;
753 layer_buffer->unaligned_height = layer_buffer->height;
Naseer Ahmed16c72b92016-07-22 20:02:31 -0400754 layer->src_rect.left = 0;
755 layer->src_rect.top = 0;
756 layer->src_rect.right = layer_buffer->width;
757 layer->src_rect.bottom = layer_buffer->height;
758 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500759
Pullakavi Srinivas3dbb0d92018-03-07 15:15:14 +0530760 if (hwc_layer->HasMetaDataRefreshRate() && layer->frame_rate > metadata_refresh_rate_) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500761 metadata_refresh_rate_ = SanitizeRefreshRate(layer->frame_rate);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500762 }
Pullakavi Srinivas3dbb0d92018-03-07 15:15:14 +0530763
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500764 display_rect_ = Union(display_rect_, layer->dst_rect);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500765 geometry_changes_ |= hwc_layer->GetGeometryChanges();
Prabhanjan Kandulaf3bc22c2016-08-03 18:59:03 +0530766
767 layer->flags.updating = true;
768 if (layer_set_.size() <= kMaxLayerCount) {
Sushil Chauhan9735cf82018-07-10 12:06:01 -0700769 layer->flags.updating = IsLayerUpdating(hwc_layer);
Prabhanjan Kandulaf3bc22c2016-08-03 18:59:03 +0530770 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500771
Tharaga Balachandran209db582019-03-25 18:56:50 -0400772 if (hwc_layer->IsColorTransformSet()) {
773 layer->flags.color_transform = true;
774 }
775
Pullakavi Srinivasad8bd012019-04-22 17:04:51 +0530776 layer_stack_.flags.mask_present |= layer->input_buffer.flags.mask_layer;
777
Sushil Chauhand1906042019-04-05 14:03:19 -0700778 if ((hwc_layer->GetDeviceSelectedCompositionType() != HWC2::Composition::Device) ||
779 (hwc_layer->GetClientRequestedCompositionType() != HWC2::Composition::Device) ||
780 layer->flags.skip) {
781 layer->update_mask.set(kClientCompRequest);
782 }
783
Xu Yang7469c4f2019-11-27 10:25:59 +0800784 if (game_supported_ && (hwc_layer->GetType() == kLayerGame)) {
Ray Zhang2ee82472019-09-05 02:53:29 +0800785 layer->flags.is_game = true;
786 layer->input_buffer.flags.game = true;
787 }
788
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500789 layer_stack_.layers.push_back(layer);
790 }
Naseer Ahmedade4ee62016-10-07 17:07:38 -0400791
Sushil Chauhan601150c2019-07-24 09:06:45 -0700792 // If layer stack needs Client composition, HWC display gets into InternalValidate state. If
793 // validation gets reset by any other thread in this state, enforce Geometry change to ensure
794 // that Client target gets composed by SF.
795 bool enforce_geometry_change = (validate_state_ == kInternalValidate) && !validated_;
796
Arun Kumar K.R3e89f792016-06-01 17:14:15 -0700797 // TODO(user): Set correctly when SDM supports geometry_changes as bitmask
Sushil Chauhand1906042019-04-05 14:03:19 -0700798
Rajavenu Kyathamef474182019-07-03 15:26:08 +0530799 layer_stack_.flags.geometry_changed = UINT32((geometry_changes_ || enforce_geometry_change ||
800 geometry_changes_on_doze_suspend_) > 0);
Rajavenu Kyathamef474182019-07-03 15:26:08 +0530801 layer_stack_.flags.config_changed = !validated_;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500802 // Append client target to the layer stack
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +0530803 Layer *sdm_client_target = client_target_->GetSDMLayer();
Sushil Chauhan9735cf82018-07-10 12:06:01 -0700804 sdm_client_target->flags.updating = IsLayerUpdating(client_target_);
Arun Kumar K.R5b821552018-12-07 08:00:15 +0530805 // Derive client target dataspace based on the color mode - bug/115482728
806 int32_t client_target_dataspace = GetDataspaceFromColorMode(GetCurrentColorMode());
807 SetClientTargetDataSpace(client_target_dataspace);
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +0530808 layer_stack_.layers.push_back(sdm_client_target);
Sushil Chauhan7cd110d2018-08-24 17:17:55 -0700809
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +0530810 // fall back frame composition to GPU when client target is 10bit
811 // TODO(user): clarify the behaviour from Client(SF) and SDM Extn -
812 // when handling 10bit FBT, as it would affect blending
Sushil Chauhan8008d602018-09-04 14:43:27 -0700813 if (Is10BitFormat(sdm_client_target->input_buffer.format)) {
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +0530814 // Must fall back to client composition
815 MarkLayersForClientComposition();
816 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500817}
818
Arun Kumar K.R536c7d62016-06-14 18:47:39 -0700819void HWCDisplay::BuildSolidFillStack() {
820 layer_stack_ = LayerStack();
821 display_rect_ = LayerRect();
822
823 layer_stack_.layers.push_back(solid_fill_layer_);
824 layer_stack_.flags.geometry_changed = 1U;
825 // Append client target to the layer stack
826 layer_stack_.layers.push_back(client_target_->GetSDMLayer());
827}
828
Ray Zhang2ee82472019-09-05 02:53:29 +0800829HWC2::Error HWCDisplay::SetLayerType(hwc2_layer_t layer_id, IQtiComposerClient::LayerType type) {
830 const auto map_layer = layer_map_.find(layer_id);
831 if (map_layer == layer_map_.end()) {
832 DLOGE("[%" PRIu64 "] SetLayerType failed to find layer", id_);
833 return HWC2::Error::BadLayer;
834 }
835
836 const auto layer = map_layer->second;
837 layer->SetLayerType(type);
838 return HWC2::Error::None;
839}
840
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500841HWC2::Error HWCDisplay::SetLayerZOrder(hwc2_layer_t layer_id, uint32_t z) {
842 const auto map_layer = layer_map_.find(layer_id);
843 if (map_layer == layer_map_.end()) {
Dileep Marchya9e388172019-09-12 11:44:19 +0530844 DLOGW("[%" PRIu64 "] updateLayerZ failed to find layer", id_);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500845 return HWC2::Error::BadLayer;
846 }
847
848 const auto layer = map_layer->second;
849 const auto z_range = layer_set_.equal_range(layer);
850 bool layer_on_display = false;
851 for (auto current = z_range.first; current != z_range.second; ++current) {
852 if (*current == layer) {
853 if ((*current)->GetZ() == z) {
854 // Don't change anything if the Z hasn't changed
855 return HWC2::Error::None;
856 }
857 current = layer_set_.erase(current);
858 layer_on_display = true;
859 break;
860 }
861 }
862
863 if (!layer_on_display) {
864 DLOGE("[%" PRIu64 "] updateLayerZ failed to find layer on display", id_);
865 return HWC2::Error::BadLayer;
866 }
867
868 layer->SetLayerZOrder(z);
869 layer_set_.emplace(layer);
870 return HWC2::Error::None;
871}
872
873HWC2::Error HWCDisplay::SetVsyncEnabled(HWC2::Vsync enabled) {
874 DLOGV("Display ID: %d enabled: %s", id_, to_string(enabled).c_str());
Naseer Ahmedf5187022017-07-24 16:15:28 -0400875 ATRACE_INT("SetVsyncState ", enabled == HWC2::Vsync::Enable ? 1 : 0);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500876 DisplayError error = kErrorNone;
877
Naseer Ahmedfac16d02017-04-04 19:59:20 -0400878 if (shutdown_pending_ || !callbacks_->VsyncCallbackRegistered()) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500879 return HWC2::Error::None;
880 }
881
882 bool state;
883 if (enabled == HWC2::Vsync::Enable)
884 state = true;
885 else if (enabled == HWC2::Vsync::Disable)
886 state = false;
887 else
888 return HWC2::Error::BadParameter;
889
890 error = display_intf_->SetVSyncState(state);
891
892 if (error != kErrorNone) {
893 if (error == kErrorShutDown) {
894 shutdown_pending_ = true;
895 return HWC2::Error::None;
896 }
897 DLOGE("Failed. enabled = %s, error = %d", to_string(enabled).c_str(), error);
898 return HWC2::Error::BadDisplay;
899 }
900
901 return HWC2::Error::None;
902}
903
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530904void HWCDisplay::PostPowerMode() {
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +0530905 if (release_fence_ == nullptr) {
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530906 return;
907 }
908
909 for (auto hwc_layer : layer_set_) {
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +0530910 shared_ptr<Fence> fence = nullptr;
911 shared_ptr<Fence> merged_fence = nullptr;
912
913 hwc_layer->PopBackReleaseFence(&fence);
914 if (fence) {
915 merged_fence = Fence::Merge(release_fence_, fence);
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530916 } else {
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +0530917 merged_fence = release_fence_;
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530918 }
919 hwc_layer->PushBackReleaseFence(merged_fence);
920 }
921
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530922 fbt_release_fence_ = release_fence_;
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530923}
924
Varun Arora78580b82018-09-10 13:59:57 -0700925HWC2::Error HWCDisplay::SetPowerMode(HWC2::PowerMode mode, bool teardown) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500926 DLOGV("display = %d, mode = %s", id_, to_string(mode).c_str());
927 DisplayState state = kStateOff;
928 bool flush_on_error = flush_on_error_;
929
930 if (shutdown_pending_) {
931 return HWC2::Error::None;
932 }
933
934 switch (mode) {
935 case HWC2::PowerMode::Off:
936 // During power off, all of the buffers are released.
937 // Do not flush until a buffer is successfully submitted again.
938 flush_on_error = false;
939 state = kStateOff;
Arun Kumar K.R51be3d12017-03-31 19:54:38 -0700940 if (tone_mapper_) {
941 tone_mapper_->Terminate();
942 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500943 break;
944 case HWC2::PowerMode::On:
945 state = kStateOn;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500946 break;
947 case HWC2::PowerMode::Doze:
948 state = kStateDoze;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500949 break;
950 case HWC2::PowerMode::DozeSuspend:
951 state = kStateDozeSuspend;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500952 break;
953 default:
954 return HWC2::Error::BadParameter;
955 }
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +0530956 shared_ptr<Fence> release_fence = nullptr;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500957
Naseer Ahmedf5187022017-07-24 16:15:28 -0400958 ATRACE_INT("SetPowerMode ", state);
Varun Arora78580b82018-09-10 13:59:57 -0700959 DisplayError error = display_intf_->SetDisplayState(state, teardown, &release_fence);
Saurabh Shaha307e8c2017-09-28 18:05:40 -0700960 validated_ = false;
Sushil Chauhan409e8442017-06-12 17:43:25 -0700961
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500962 if (error == kErrorNone) {
963 flush_on_error_ = flush_on_error;
964 } else {
965 if (error == kErrorShutDown) {
966 shutdown_pending_ = true;
967 return HWC2::Error::None;
968 }
969 DLOGE("Set state failed. Error = %d", error);
970 return HWC2::Error::BadParameter;
971 }
972
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530973 // Update release fence.
974 release_fence_ = release_fence;
Varun Aroraf027a222018-11-14 17:38:16 -0800975 current_power_mode_ = mode;
Rajavenu Kyatham50966d82019-08-06 18:02:36 +0530976
977 // Close the release fences in synchronous power updates
978 if (!async_power_mode_) {
979 PostPowerMode();
980 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500981 return HWC2::Error::None;
982}
983
984HWC2::Error HWCDisplay::GetClientTargetSupport(uint32_t width, uint32_t height, int32_t format,
985 int32_t dataspace) {
Rajavenu Kyathamc79fceb2017-09-01 20:41:43 +0530986 ColorMetaData color_metadata = {};
Rajavenu Kyatham78b20862017-10-30 17:53:30 +0530987 if (dataspace != HAL_DATASPACE_UNKNOWN) {
Arun Kumar K.R4aa2c4c2018-05-14 11:45:00 +0530988 dataspace = TranslateFromLegacyDataspace(dataspace);
Rajavenu Kyatham78b20862017-10-30 17:53:30 +0530989 GetColorPrimary(dataspace, &(color_metadata.colorPrimaries));
990 GetTransfer(dataspace, &(color_metadata.transfer));
991 GetRange(dataspace, &(color_metadata.range));
992 }
Rajavenu Kyathamc79fceb2017-09-01 20:41:43 +0530993
Gousemoodhin Nadafa990d722018-04-04 08:33:43 +0530994 LayerBufferFormat sdm_format = HWCLayer::GetSDMFormat(format, 0);
Rajavenu Kyathamc79fceb2017-09-01 20:41:43 +0530995 if (display_intf_->GetClientTargetSupport(width, height, sdm_format,
996 color_metadata) != kErrorNone) {
997 return HWC2::Error::Unsupported;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500998 }
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +0530999
Rajavenu Kyathamc79fceb2017-09-01 20:41:43 +05301000 return HWC2::Error::None;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001001}
1002
Naseer Ahmede7a77982018-06-04 10:56:04 -04001003HWC2::Error HWCDisplay::GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes) {
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301004 if (out_modes == nullptr) {
1005 *out_num_modes = 1;
1006 } else if (out_modes && *out_num_modes > 0) {
1007 *out_num_modes = 1;
Naseer Ahmede7a77982018-06-04 10:56:04 -04001008 out_modes[0] = ColorMode::NATIVE;
Arun Kumar K.R29cd6582016-05-10 19:12:45 -07001009 }
Naseer Ahmede7a77982018-06-04 10:56:04 -04001010 return HWC2::Error::None;
1011}
Arun Kumar K.R29cd6582016-05-10 19:12:45 -07001012
Naseer Ahmede7a77982018-06-04 10:56:04 -04001013HWC2::Error HWCDisplay::GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
1014 RenderIntent *out_intents) {
1015 if (mode != ColorMode::NATIVE) {
1016 return HWC2::Error::Unsupported;
1017 }
1018 if (out_intents == nullptr) {
1019 *out_num_intents = 1;
1020 } else if (out_intents && *out_num_intents > 0) {
1021 *out_num_intents = 1;
1022 out_intents[0] = RenderIntent::COLORIMETRIC;
1023 }
Arun Kumar K.R29cd6582016-05-10 19:12:45 -07001024 return HWC2::Error::None;
1025}
1026
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001027HWC2::Error HWCDisplay::GetDisplayConfigs(uint32_t *out_num_configs, hwc2_config_t *out_configs) {
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301028 if (out_num_configs == nullptr) {
1029 return HWC2::Error::BadParameter;
1030 }
1031
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001032 if (out_configs == nullptr) {
Rajavenu Kyatham40fc5382017-07-12 18:36:55 +05301033 *out_num_configs = num_configs_;
1034 return HWC2::Error::None;
1035 }
1036
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301037 *out_num_configs = std::min(*out_num_configs, num_configs_);
Pullakavi Srinivas9189e602018-12-19 16:58:07 +05301038
1039 // Expose all unique config ids to cleint.
1040 uint32_t i = 0;
1041 for (auto &info : variable_config_map_) {
1042 if (i == *out_num_configs) {
1043 break;
1044 }
1045 out_configs[i++] = info.first;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001046 }
Arun Kumar K.R29cd6582016-05-10 19:12:45 -07001047
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001048 return HWC2::Error::None;
1049}
1050
Naseer Ahmed8584a0f2020-02-19 22:23:30 -05001051HWC2::Error HWCDisplay::GetDisplayAttribute(hwc2_config_t config, HwcAttribute attribute,
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001052 int32_t *out_value) {
Pullakavi Srinivas9189e602018-12-19 16:58:07 +05301053 if (variable_config_map_.find(config) == variable_config_map_.end()) {
Pullakavi Srinivas8b33a282018-11-01 12:45:38 +05301054 DLOGE("Get variable config failed");
1055 return HWC2::Error::BadDisplay;
Arun Kumar K.R8da7f502016-06-07 17:45:50 -07001056 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001057
Pullakavi Srinivas9189e602018-12-19 16:58:07 +05301058 DisplayConfigVariableInfo variable_config = variable_config_map_.at(config);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001059 switch (attribute) {
Naseer Ahmed8584a0f2020-02-19 22:23:30 -05001060 case HwcAttribute::VSYNC_PERIOD:
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001061 *out_value = INT32(variable_config.vsync_period_ns);
1062 break;
Naseer Ahmed8584a0f2020-02-19 22:23:30 -05001063 case HwcAttribute::WIDTH:
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001064 *out_value = INT32(variable_config.x_pixels);
1065 break;
Naseer Ahmed8584a0f2020-02-19 22:23:30 -05001066 case HwcAttribute::HEIGHT:
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001067 *out_value = INT32(variable_config.y_pixels);
1068 break;
Naseer Ahmed8584a0f2020-02-19 22:23:30 -05001069 case HwcAttribute::DPI_X:
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001070 *out_value = INT32(variable_config.x_dpi * 1000.0f);
1071 break;
Naseer Ahmed8584a0f2020-02-19 22:23:30 -05001072 case HwcAttribute::DPI_Y:
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001073 *out_value = INT32(variable_config.y_dpi * 1000.0f);
1074 break;
Naseer Ahmed8584a0f2020-02-19 22:23:30 -05001075 case HwcAttribute::CONFIG_GROUP:
Sushil Chauhanf8541202020-02-03 23:14:36 -08001076 *out_value = GetDisplayConfigGroup(variable_config);
1077 break;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001078 default:
Naseer Ahmed8584a0f2020-02-19 22:23:30 -05001079 DLOGW("Spurious attribute type = %s", composer_V2_4::toString(attribute).c_str());
Naseer Ahmedf937bd02017-04-03 19:10:28 -04001080 *out_value = -1;
Naseer Ahmed8584a0f2020-02-19 22:23:30 -05001081 return HWC2::Error::BadParameter;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001082 }
1083
1084 return HWC2::Error::None;
1085}
1086
1087HWC2::Error HWCDisplay::GetDisplayName(uint32_t *out_size, char *out_name) {
1088 // TODO(user): Get panel name and EDID name and populate it here
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301089 if (out_size == nullptr) {
1090 return HWC2::Error::BadParameter;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001091 }
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301092
1093 std::string name;
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +05301094 switch (type_) {
1095 case kBuiltIn:
1096 name = "Built-in Display";
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301097 break;
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +05301098 case kPluggable:
1099 name = "Pluggable Display";
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301100 break;
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +05301101 case kVirtual:
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301102 name = "Virtual Display";
1103 break;
1104 default:
1105 name = "Unknown";
1106 break;
1107 }
1108
1109 if (out_name == nullptr) {
1110 *out_size = UINT32(name.size()) + 1;
1111 } else {
1112 *out_size = std::min((UINT32(name.size()) + 1), *out_size);
1113 if (*out_size > 0) {
Ravikanth Tunikie8501fc2018-08-10 17:46:15 +05301114 strlcpy(out_name, name.c_str(), *out_size);
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301115 out_name[*out_size - 1] = '\0';
1116 } else {
1117 DLOGW("Invalid size requested");
1118 }
1119 }
1120
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001121 return HWC2::Error::None;
1122}
1123
1124HWC2::Error HWCDisplay::GetDisplayType(int32_t *out_type) {
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +05301125 if (out_type == nullptr) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001126 return HWC2::Error::BadParameter;
1127 }
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +05301128
1129 *out_type = HWC2_DISPLAY_TYPE_PHYSICAL;
1130
1131 return HWC2::Error::None;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001132}
1133
Naseer Ahmeda6782e42018-06-04 10:56:04 -04001134HWC2::Error HWCDisplay::GetPerFrameMetadataKeys(uint32_t *out_num_keys,
1135 PerFrameMetadataKey *out_keys) {
1136 if (out_num_keys == nullptr) {
1137 return HWC2::Error::BadParameter;
1138 }
Gousemoodhin Nadaf4b096d02019-10-24 15:39:59 +05301139
1140 DisplayConfigFixedInfo fixed_info = {};
1141 display_intf_->GetConfig(&fixed_info);
1142 uint32_t num_keys = 0;
1143 if (fixed_info.hdr_plus_supported) {
1144 num_keys = UINT32(PerFrameMetadataKey::HDR10_PLUS_SEI) + 1;
1145 } else {
1146 num_keys = UINT32(PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL) + 1;
1147 }
1148 if (out_keys == nullptr) {
1149 *out_num_keys = num_keys;
1150 } else {
1151 uint32_t max_out_key_elements = std::min(*out_num_keys, num_keys);
1152 for (int32_t i = 0; i < max_out_key_elements; i++) {
1153 out_keys[i] = static_cast<PerFrameMetadataKey>(i);
1154 }
Naseer Ahmeda6782e42018-06-04 10:56:04 -04001155 }
1156 return HWC2::Error::None;
1157}
1158
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001159HWC2::Error HWCDisplay::GetActiveConfig(hwc2_config_t *out_config) {
Rajavenu Kyatham40fc5382017-07-12 18:36:55 +05301160 if (out_config == nullptr) {
1161 return HWC2::Error::BadDisplay;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001162 }
Rajavenu Kyatham40fc5382017-07-12 18:36:55 +05301163
Pullakavi Srinivas81fee962019-07-26 15:49:32 +05301164 if (pending_config_) {
1165 *out_config = pending_config_index_;
1166 } else {
1167 GetActiveDisplayConfig(out_config);
1168 }
1169
Pullakavi Srinivas9189e602018-12-19 16:58:07 +05301170 if (*out_config < hwc_config_map_.size()) {
1171 *out_config = hwc_config_map_.at(*out_config);
1172 }
Rajavenu Kyatham40fc5382017-07-12 18:36:55 +05301173 return HWC2::Error::None;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001174}
1175
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05301176HWC2::Error HWCDisplay::SetClientTarget(buffer_handle_t target, shared_ptr<Fence> acquire_fence,
Naseer Ahmeda20c4c02016-06-03 17:48:28 -04001177 int32_t dataspace, hwc_region_t damage) {
Naseer Ahmed093fd322016-05-03 22:22:09 -04001178 // TODO(user): SurfaceFlinger gives us a null pointer here when doing full SDE composition
1179 // The error is problematic for layer caching as it would overwrite our cached client target.
1180 // Reported bug 28569722 to resolve this.
1181 // For now, continue to use the last valid buffer reported to us for layer caching.
1182 if (target == nullptr) {
1183 return HWC2::Error::None;
1184 }
Naseer Ahmede3f007a2016-06-07 18:13:28 -04001185
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05301186 if (acquire_fence == nullptr) {
Sushil Chauhan1b32e082018-10-04 13:31:44 -07001187 DLOGW("acquire_fence is zero");
Naseer Ahmede3f007a2016-06-07 18:13:28 -04001188 return HWC2::Error::BadParameter;
1189 }
1190
Namit Solanki1ec25242017-10-18 16:45:22 +05301191 Layer *sdm_layer = client_target_->GetSDMLayer();
Mahesh Aiaf3a1f992019-01-16 13:07:42 -08001192 sdm_layer->frame_rate = std::min(current_refresh_rate_, HWCDisplay::GetThrottlingRefreshRate());
Naseer Ahmeda20c4c02016-06-03 17:48:28 -04001193 client_target_->SetLayerSurfaceDamage(damage);
Arun Kumar K.R5b821552018-12-07 08:00:15 +05301194 int translated_dataspace = TranslateFromLegacyDataspace(dataspace);
1195 if (client_target_->GetLayerDataspace() != translated_dataspace) {
1196 DLOGW("New Dataspace = %d not matching Dataspace from color mode = %d",
1197 translated_dataspace, client_target_->GetLayerDataspace());
1198 return HWC2::Error::BadParameter;
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +05301199 }
Saurabh Dubey66b807e2018-05-11 10:05:07 +05301200 client_target_->SetLayerBuffer(target, acquire_fence);
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +05301201
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001202 return HWC2::Error::None;
1203}
1204
1205HWC2::Error HWCDisplay::SetActiveConfig(hwc2_config_t config) {
Gurpreet Singh Dhamia4276882019-04-12 10:30:58 -07001206 DTRACE_SCOPED();
1207
Pullakavi Srinivas81fee962019-07-26 15:49:32 +05301208 hwc2_config_t current_config = 0;
1209 GetActiveConfig(&current_config);
1210 if (current_config == config) {
1211 return HWC2::Error::None;
Naseer Ahmedf937bd02017-04-03 19:10:28 -04001212 }
Naseer Ahmedd7b8c512019-04-17 20:10:36 -04001213 DLOGI("Active configuration changed to: %d", config);
Pullakavi Srinivas81fee962019-07-26 15:49:32 +05301214
1215 // Store config index to be applied upon refresh.
1216 pending_config_ = true;
1217 pending_config_index_ = config;
1218
Saurabh Shaha307e8c2017-09-28 18:05:40 -07001219 validated_ = false;
Pullakavi Srinivas81fee962019-07-26 15:49:32 +05301220
1221 // Trigger refresh. This config gets applied on next commit.
1222 callbacks_->Refresh(id_);
1223
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001224 return HWC2::Error::None;
1225}
1226
Arun Kumar K.R8da7f502016-06-07 17:45:50 -07001227DisplayError HWCDisplay::SetMixerResolution(uint32_t width, uint32_t height) {
1228 return kErrorNotSupported;
1229}
1230
Sushil Chauhan267a6192018-06-06 18:41:47 -07001231HWC2::Error HWCDisplay::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type,
1232 int32_t format, bool post_processed) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001233 dump_frame_count_ = count;
1234 dump_frame_index_ = 0;
1235 dump_input_layers_ = ((bit_mask_layer_type & (1 << INPUT_LAYER_DUMP)) != 0);
1236
Arun Kumar K.R51be3d12017-03-31 19:54:38 -07001237 if (tone_mapper_) {
1238 tone_mapper_->SetFrameDumpConfig(count);
1239 }
1240
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001241 DLOGI("num_frame_dump %d, input_layer_dump_enable %d", dump_frame_count_, dump_input_layers_);
Saurabh Shaha307e8c2017-09-28 18:05:40 -07001242 validated_ = false;
Mathew Joseph Karimpanaldbd64f82017-10-06 10:13:38 +05301243 return HWC2::Error::None;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001244}
1245
Varun Aroraf027a222018-11-14 17:38:16 -08001246HWC2::PowerMode HWCDisplay::GetCurrentPowerMode() {
1247 return current_power_mode_;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001248}
1249
1250DisplayError HWCDisplay::VSync(const DisplayEventVSync &vsync) {
1251 callbacks_->Vsync(id_, vsync.timestamp);
1252 return kErrorNone;
1253}
1254
1255DisplayError HWCDisplay::Refresh() {
Varun Aroradff7d8d2019-08-05 18:12:43 -07001256 callbacks_->Refresh(id_);
1257 return kErrorNone;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001258}
1259
1260DisplayError HWCDisplay::CECMessage(char *message) {
1261 if (qservice_) {
1262 qservice_->onCECMessageReceived(message, 0);
1263 } else {
1264 DLOGW("Qservice instance not available.");
1265 }
1266
1267 return kErrorNone;
1268}
1269
Sushil Chauhan409e8442017-06-12 17:43:25 -07001270DisplayError HWCDisplay::HandleEvent(DisplayEvent event) {
1271 switch (event) {
Namit Solanki5b428dc2018-02-27 11:39:05 +05301272 case kIdleTimeout: {
Mathew Joseph Karimpanal4b35b272018-11-27 10:56:49 +05301273 SCOPE_LOCK(HWCSession::locker_[id_]);
Namit Solanki5b428dc2018-02-27 11:39:05 +05301274 if (pending_commit_) {
1275 // If idle timeout event comes in between prepare
1276 // and commit, drop it since device is not really
1277 // idle.
1278 return kErrorNotSupported;
1279 }
1280 validated_ = false;
1281 break;
1282 }
Gopikrishnaiah Anandan72f5a982019-10-02 14:26:49 -07001283 case kInvalidateDisplay:
Ramakant Singh99370542019-10-15 11:54:39 +05301284 case kThermalEvent: {
Mathew Joseph Karimpanal4b35b272018-11-27 10:56:49 +05301285 SEQUENCE_WAIT_SCOPE_LOCK(HWCSession::locker_[id_]);
Saurabh Shaha307e8c2017-09-28 18:05:40 -07001286 validated_ = false;
1287 } break;
Ramakant Singh99370542019-10-15 11:54:39 +05301288 case kPanelDeadEvent:
Varun Arora7c8ee542018-05-01 20:58:16 -07001289 case kDisplayPowerResetEvent: {
Manoj Kumar AVM92df9782019-11-14 08:36:32 -08001290 // Mutex scope
1291 {
1292 SEQUENCE_WAIT_SCOPE_LOCK(HWCSession::locker_[id_]);
1293 validated_ = false;
1294 }
1295 // TODO(user): Following scenario need to be addressed
1296 // If panel or HW is in bad state for either ESD or HWR, there is no acquired lock between
1297 // this scope and call to DisplayPowerReset.
1298 // Prepare or commit could operate on the display since locker_[id_] is free and most likely
1299 // result in a failure since ESD/HWR has been requested during this time period.
Varun Arora7c8ee542018-05-01 20:58:16 -07001300 if (event_handler_) {
1301 event_handler_->DisplayPowerReset();
1302 } else {
Varun Aroraf027a222018-11-14 17:38:16 -08001303 DLOGW("Cannot execute DisplayPowerReset (client_id = %d), event_handler_ is nullptr",
1304 id_);
Varun Arora7c8ee542018-05-01 20:58:16 -07001305 }
1306 } break;
Sushil Chauhan43102c72019-06-21 02:06:24 -07001307 case kIdlePowerCollapse:
1308 break;
Sushil Chauhan409e8442017-06-12 17:43:25 -07001309 default:
1310 DLOGW("Unknown event: %d", event);
1311 break;
1312 }
1313
1314 return kErrorNone;
1315}
1316
Lakshmi Narayana Kalavalae0127eb2019-12-03 11:07:26 -08001317DisplayError HWCDisplay::HistogramEvent(int /* fd */, uint32_t /* blob_fd */) {
1318 return kErrorNone;
1319}
1320
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001321HWC2::Error HWCDisplay::PrepareLayerStack(uint32_t *out_num_types, uint32_t *out_num_requests) {
1322 layer_changes_.clear();
1323 layer_requests_.clear();
Sushil Chauhane3a9fd02017-10-12 18:00:05 -07001324 has_client_composition_ = false;
1325
Gurpreet Singh Dhamia4276882019-04-12 10:30:58 -07001326 DTRACE_SCOPED();
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001327 if (shutdown_pending_) {
Sushil Chauhane3a9fd02017-10-12 18:00:05 -07001328 validated_ = false;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001329 return HWC2::Error::BadDisplay;
1330 }
1331
Sushil Chauhan36c059a2018-06-28 11:39:01 -07001332 if (CanSkipSdmPrepare(out_num_types, out_num_requests)) {
1333 return ((*out_num_types > 0) ? HWC2::Error::HasChanges : HWC2::Error::None);
1334 }
1335
Pullakavi Srinivas3dbb0d92018-03-07 15:15:14 +05301336 UpdateRefreshRate();
Pullakavi Srinivas81fee962019-07-26 15:49:32 +05301337 UpdateActiveConfig();
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -07001338 DisplayError error = display_intf_->Prepare(&layer_stack_);
1339 if (error != kErrorNone) {
1340 if (error == kErrorShutDown) {
1341 shutdown_pending_ = true;
Padmanabhan Komandurue74cf4f2019-04-25 17:38:43 -07001342 } else if (error == kErrorPermission) {
1343 WaitOnPreviousFence();
1344 MarkLayersForGPUBypass();
Rajavenu Kyathamef474182019-07-03 15:26:08 +05301345 geometry_changes_on_doze_suspend_ |= geometry_changes_;
Padmanabhan Komandurue74cf4f2019-04-25 17:38:43 -07001346 } else {
Varun Arora2d1fcb72019-03-21 17:43:06 -07001347 DLOGW("Prepare failed. Error = %d", error);
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -07001348 // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
1349 // so that previous buffer and fences are released, and override the error.
1350 flush_ = true;
Padmanabhan Komandurue74cf4f2019-04-25 17:38:43 -07001351 validated_ = false;
Ramakant Singh635c5552019-03-26 13:06:51 +05301352 // Prepare cycle can fail on a newly connected display if insufficient pipes
1353 // are available at this moment. Trigger refresh so that the other displays
1354 // can free up pipes and a valid content can be attached to virtual display.
1355 callbacks_->Refresh(id_);
Padmanabhan Komandurue74cf4f2019-04-25 17:38:43 -07001356 return HWC2::Error::BadDisplay;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001357 }
Rajavenu Kyatham870b7b22019-11-05 17:58:17 +05301358 } else {
1359 // clear geometry_changes_on_doze_suspend_ on successful prepare.
1360 geometry_changes_on_doze_suspend_ = GeometryChanges::kNone;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001361 }
1362
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001363 for (auto hwc_layer : layer_set_) {
1364 Layer *layer = hwc_layer->GetSDMLayer();
1365 LayerComposition &composition = layer->composition;
1366
Pullakavi Srinivas1ae4acb2019-11-18 19:33:45 +05301367 if (composition == kCompositionSDE || composition == kCompositionStitch) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001368 layer_requests_[hwc_layer->GetId()] = HWC2::LayerRequest::ClearClientTarget;
1369 }
1370
Arun Kumar K.R2c0ff8d2016-06-01 16:56:52 -07001371 HWC2::Composition requested_composition = hwc_layer->GetClientRequestedCompositionType();
Arun Kumar K.R3e89f792016-06-01 17:14:15 -07001372 // Set SDM composition to HWC2 type in HWCLayer
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001373 hwc_layer->SetComposition(composition);
Arun Kumar K.R2c0ff8d2016-06-01 16:56:52 -07001374 HWC2::Composition device_composition = hwc_layer->GetDeviceSelectedCompositionType();
Sushil Chauhane3a9fd02017-10-12 18:00:05 -07001375 if (device_composition == HWC2::Composition::Client) {
1376 has_client_composition_ = true;
1377 }
Arun Kumar K.R2c0ff8d2016-06-01 16:56:52 -07001378 // Update the changes list only if the requested composition is different from SDM comp type
Arun Kumar K.R2c0ff8d2016-06-01 16:56:52 -07001379 if (requested_composition != device_composition) {
1380 layer_changes_[hwc_layer->GetId()] = device_composition;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001381 }
Sushil Chauhan409e8442017-06-12 17:43:25 -07001382 hwc_layer->ResetValidation();
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001383 }
Sushil Chauhane3a9fd02017-10-12 18:00:05 -07001384
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +05301385 client_target_->ResetValidation();
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001386 *out_num_types = UINT32(layer_changes_.size());
1387 *out_num_requests = UINT32(layer_requests_.size());
Sushil Chauhane3a9fd02017-10-12 18:00:05 -07001388 validate_state_ = kNormalValidate;
1389 validated_ = true;
Ramkumar Radhakrishnan9335ef42018-05-15 13:41:33 -07001390 layer_stack_invalid_ = false;
Sushil Chauhane3a9fd02017-10-12 18:00:05 -07001391
1392 return ((*out_num_types > 0) ? HWC2::Error::HasChanges : HWC2::Error::None);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001393}
1394
1395HWC2::Error HWCDisplay::AcceptDisplayChanges() {
Naseer Ahmed06ccd302016-10-25 12:46:33 -04001396 if (layer_set_.empty()) {
1397 return HWC2::Error::None;
1398 }
1399
Saurabh Shaha307e8c2017-09-28 18:05:40 -07001400 if (!validated_) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001401 return HWC2::Error::NotValidated;
1402 }
Naseer Ahmed63c2b5d2016-08-25 16:54:41 -04001403
1404 for (const auto& change : layer_changes_) {
1405 auto hwc_layer = layer_map_[change.first];
1406 auto composition = change.second;
Naseer Ahmed06ccd302016-10-25 12:46:33 -04001407 if (hwc_layer != nullptr) {
1408 hwc_layer->UpdateClientCompositionType(composition);
1409 } else {
1410 DLOGW("Invalid layer: %" PRIu64, change.first);
1411 }
Naseer Ahmed63c2b5d2016-08-25 16:54:41 -04001412 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001413 return HWC2::Error::None;
1414}
1415
1416HWC2::Error HWCDisplay::GetChangedCompositionTypes(uint32_t *out_num_elements,
1417 hwc2_layer_t *out_layers, int32_t *out_types) {
Naseer Ahmedb8bf21b2016-06-17 16:15:47 -04001418 if (layer_set_.empty()) {
1419 return HWC2::Error::None;
1420 }
1421
Saurabh Shaha307e8c2017-09-28 18:05:40 -07001422 if (!validated_) {
Arun Kumar K.R2c0ff8d2016-06-01 16:56:52 -07001423 DLOGW("Display is not validated");
1424 return HWC2::Error::NotValidated;
1425 }
Arun Kumar K.R1018d5b2017-06-08 13:51:05 +05301426
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001427 *out_num_elements = UINT32(layer_changes_.size());
1428 if (out_layers != nullptr && out_types != nullptr) {
1429 int i = 0;
1430 for (auto change : layer_changes_) {
1431 out_layers[i] = change.first;
1432 out_types[i] = INT32(change.second);
1433 i++;
1434 }
1435 }
1436 return HWC2::Error::None;
1437}
1438
1439HWC2::Error HWCDisplay::GetReleaseFences(uint32_t *out_num_elements, hwc2_layer_t *out_layers,
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05301440 std::vector<shared_ptr<Fence>> *out_fences) {
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301441 if (out_num_elements == nullptr) {
1442 return HWC2::Error::BadParameter;
1443 }
1444
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001445 if (out_layers != nullptr && out_fences != nullptr) {
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301446 *out_num_elements = std::min(*out_num_elements, UINT32(layer_set_.size()));
1447 auto it = layer_set_.begin();
1448 for (uint32_t i = 0; i < *out_num_elements; i++, it++) {
1449 auto hwc_layer = *it;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001450 out_layers[i] = hwc_layer->GetId();
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05301451
1452 shared_ptr<Fence> &fence = (*out_fences)[i];
1453 hwc_layer->PopFrontReleaseFence(&fence);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001454 }
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301455 } else {
1456 *out_num_elements = UINT32(layer_set_.size());
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001457 }
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301458
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001459 return HWC2::Error::None;
1460}
1461
1462HWC2::Error HWCDisplay::GetDisplayRequests(int32_t *out_display_requests,
1463 uint32_t *out_num_elements, hwc2_layer_t *out_layers,
1464 int32_t *out_layer_requests) {
Naseer Ahmedb8bf21b2016-06-17 16:15:47 -04001465 if (layer_set_.empty()) {
1466 return HWC2::Error::None;
1467 }
1468
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301469 if (out_display_requests == nullptr || out_num_elements == nullptr) {
1470 return HWC2::Error::BadParameter;
1471 }
1472
Arun Kumar K.R1018d5b2017-06-08 13:51:05 +05301473 // No display requests for now
1474 // Use for sharing blit buffers and
1475 // writing wfd buffer directly to output if there is full GPU composition
1476 // and no color conversion needed
Saurabh Shaha307e8c2017-09-28 18:05:40 -07001477 if (!validated_) {
Naseer Ahmedaddcabf2016-05-04 15:49:29 -04001478 DLOGW("Display is not validated");
1479 return HWC2::Error::NotValidated;
1480 }
Arun Kumar K.R1018d5b2017-06-08 13:51:05 +05301481
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001482 *out_display_requests = 0;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001483 if (out_layers != nullptr && out_layer_requests != nullptr) {
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301484 *out_num_elements = std::min(*out_num_elements, UINT32(layer_requests_.size()));
1485 auto it = layer_requests_.begin();
1486 for (uint32_t i = 0; i < *out_num_elements; i++, it++) {
1487 out_layers[i] = it->first;
1488 out_layer_requests[i] = INT32(it->second);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001489 }
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301490 } else {
1491 *out_num_elements = UINT32(layer_requests_.size());
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001492 }
Rajavenu Kyatham7ac83682016-10-10 18:31:13 +05301493
1494 auto client_target_layer = client_target_->GetSDMLayer();
1495 if (client_target_layer->request.flags.flip_buffer) {
1496 *out_display_requests = INT32(HWC2::DisplayRequest::FlipClientTarget);
1497 }
1498
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001499 return HWC2::Error::None;
1500}
1501
Arun Kumar K.Rf28957a2017-01-10 17:36:52 -08001502HWC2::Error HWCDisplay::GetHdrCapabilities(uint32_t *out_num_types, int32_t *out_types,
1503 float *out_max_luminance,
1504 float *out_max_average_luminance,
1505 float *out_min_luminance) {
Arun Kumar K.R0e10fd22017-10-11 14:42:11 +05301506 if (out_num_types == nullptr || out_max_luminance == nullptr ||
1507 out_max_average_luminance == nullptr || out_min_luminance == nullptr) {
1508 return HWC2::Error::BadParameter;
1509 }
1510
Arun Kumar K.Rf28957a2017-01-10 17:36:52 -08001511 DisplayConfigFixedInfo fixed_info = {};
1512 display_intf_->GetConfig(&fixed_info);
1513
Sushil Chauhan4fac1962017-05-19 14:00:19 -07001514 if (!fixed_info.hdr_supported) {
1515 *out_num_types = 0;
1516 DLOGI("HDR is not supported");
1517 return HWC2::Error::None;
1518 }
1519
Gousemoodhin Nadaf4b096d02019-10-24 15:39:59 +05301520 uint32_t num_types = 0;
1521 if (fixed_info.hdr_plus_supported) {
1522 num_types = UINT32(Hdr::HDR10_PLUS) - 1;
Arun Kumar K.Rf28957a2017-01-10 17:36:52 -08001523 } else {
Gousemoodhin Nadaf4b096d02019-10-24 15:39:59 +05301524 num_types = UINT32(Hdr::HLG) - 1;
1525 }
1526
1527 // We support HDR10, HLG and HDR10_PLUS.
1528 if (out_types == nullptr) {
1529 *out_num_types = num_types;
1530 } else {
1531 uint32_t max_out_types = std::min(*out_num_types, num_types);
1532 int32_t type = static_cast<int32_t>(Hdr::DOLBY_VISION);
1533 for (int32_t i = 0; i < max_out_types; i++) {
1534 while (type == static_cast<int32_t>(Hdr::DOLBY_VISION) /* Skip list */) {
1535 // Skip the type
1536 type++;
1537 }
1538 if (type > (num_types + 1)) {
1539 break;
1540 }
1541 out_types[i] = type++;
1542 }
Sushil Chauhanaa8be832018-08-31 13:38:20 -07001543 *out_max_luminance = fixed_info.max_luminance;
1544 *out_max_average_luminance = fixed_info.average_luminance;
1545 *out_min_luminance = fixed_info.min_luminance;
Arun Kumar K.Rf28957a2017-01-10 17:36:52 -08001546 }
1547
1548 return HWC2::Error::None;
1549}
1550
1551
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001552HWC2::Error HWCDisplay::CommitLayerStack(void) {
Pullakavi Srinivase52bfff2018-09-04 11:13:17 +05301553 if (flush_) {
1554 return HWC2::Error::None;
1555 }
1556
Gurpreet Singh Dhamia4276882019-04-12 10:30:58 -07001557 DTRACE_SCOPED();
1558
Saurabh Shaha307e8c2017-09-28 18:05:40 -07001559 if (!validated_) {
Saurabh Dubeyd90a6a42017-10-24 16:28:01 +05301560 DLOGV_IF(kTagClient, "Display %d is not validated", id_);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001561 return HWC2::Error::NotValidated;
1562 }
1563
Saurabh Shah41183042018-01-15 14:55:46 -08001564 if (shutdown_pending_ || layer_set_.empty()) {
1565 return HWC2::Error::None;
1566 }
1567
Padmanabhan Komandurue74cf4f2019-04-25 17:38:43 -07001568 if (skip_commit_) {
1569 DLOGV_IF(kTagClient, "Skipping Refresh on display %d", id_);
1570 return HWC2::Error::None;
1571 }
1572
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001573 DumpInputBuffers();
1574
Pullakavi Srinivase52bfff2018-09-04 11:13:17 +05301575 DisplayError error = kErrorUndefined;
1576 int status = 0;
1577 if (tone_mapper_) {
1578 if (NeedsToneMap(layer_stack_)) {
1579 status = tone_mapper_->HandleToneMap(&layer_stack_);
1580 if (status != 0) {
1581 DLOGE("Error handling HDR in ToneMapper");
Arun Kumar K.R51be3d12017-03-31 19:54:38 -07001582 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001583 } else {
Pullakavi Srinivase52bfff2018-09-04 11:13:17 +05301584 tone_mapper_->Terminate();
1585 }
1586 }
Padmanabhan Komanduru13b5e102019-12-03 12:35:09 +05301587
1588 if (elapse_timestamp_) {
1589 layer_stack_.elapse_timestamp = elapse_timestamp_;
1590 }
1591
Pullakavi Srinivase52bfff2018-09-04 11:13:17 +05301592 error = display_intf_->Commit(&layer_stack_);
1593
1594 if (error == kErrorNone) {
1595 // A commit is successfully submitted, start flushing on failure now onwards.
1596 flush_on_error_ = true;
Mathew Joseph Karimpanalabe3b3d2018-11-27 17:25:40 +05301597 first_cycle_ = false;
Pullakavi Srinivase52bfff2018-09-04 11:13:17 +05301598 } else {
1599 if (error == kErrorShutDown) {
1600 shutdown_pending_ = true;
1601 return HWC2::Error::Unsupported;
1602 } else if (error == kErrorNotValidated) {
1603 validated_ = false;
1604 return HWC2::Error::NotValidated;
1605 } else if (error != kErrorPermission) {
1606 DLOGE("Commit failed. Error = %d", error);
1607 // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
1608 // so that previous buffer and fences are released, and override the error.
1609 flush_ = true;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001610 }
1611 }
1612
Sushil Chauhane3a9fd02017-10-12 18:00:05 -07001613 validate_state_ = kSkipValidate;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001614 return HWC2::Error::None;
1615}
1616
Dileep Marchyaad668432019-12-02 10:44:52 +05301617HWC2::Error HWCDisplay::PostCommitLayerStack(shared_ptr<Fence> *out_retire_fence) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001618 auto status = HWC2::Error::None;
1619
1620 // Do no call flush on errors, if a successful buffer is never submitted.
1621 if (flush_ && flush_on_error_) {
Pullakavi Srinivas0a1dba62018-07-02 15:49:11 +05301622 display_intf_->Flush(&layer_stack_);
Saurabh Shaha307e8c2017-09-28 18:05:40 -07001623 validated_ = false;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001624 }
1625
Arun Kumar K.R51be3d12017-03-31 19:54:38 -07001626 if (tone_mapper_ && tone_mapper_->IsActive()) {
1627 tone_mapper_->PostCommit(&layer_stack_);
1628 }
1629
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001630 // TODO(user): No way to set the client target release fence on SF
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05301631 shared_ptr<Fence> client_target_release_fence =
1632 client_target_->GetSDMLayer()->input_buffer.release_fence;
1633 if (client_target_release_fence) {
1634 fbt_release_fence_ = client_target_release_fence;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001635 }
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +05301636 client_target_->ResetGeometryChanges();
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001637
1638 for (auto hwc_layer : layer_set_) {
1639 hwc_layer->ResetGeometryChanges();
1640 Layer *layer = hwc_layer->GetSDMLayer();
Arun Kumar K.R9c19cdd2016-11-21 16:48:43 -08001641 LayerBuffer *layer_buffer = &layer->input_buffer;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001642
1643 if (!flush_) {
1644 // If swapinterval property is set to 0 or for single buffer layers, do not update f/w
1645 // release fences and discard fences from driver
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05301646 if (!swap_interval_zero_ && !layer->flags.single_buffer) {
Pullakavi Srinivasad8bd012019-04-22 17:04:51 +05301647 // It may so happen that layer gets marked to GPU & app layer gets queued
1648 // to MDP for composition. In those scenarios, release fence of buffer should
1649 // have mdp and gpu sync points merged.
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05301650 hwc_layer->PushBackReleaseFence(layer_buffer->release_fence);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001651 }
Saurabh Shah42c8d912017-08-31 17:19:30 -07001652 } else {
Padmanabhan Komandurue74cf4f2019-04-25 17:38:43 -07001653 // In case of flush or display paused, we don't return an error to f/w, so it will
1654 // get a release fence out of the hwc_layer's release fence queue
1655 // We should push a -1 to preserve release fence circulation semantics.
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05301656 hwc_layer->PushBackReleaseFence(nullptr);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001657 }
Saurabh Shah41183042018-01-15 14:55:46 -08001658
1659 layer->request.flags = {};
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001660 }
1661
Saurabh Shah41183042018-01-15 14:55:46 -08001662 client_target_->GetSDMLayer()->request.flags = {};
Pullakavi Srinivas0a1dba62018-07-02 15:49:11 +05301663 // if swapinterval property is set to 0 then close and reset the list retire fence
Dileep Marchyaad668432019-12-02 10:44:52 +05301664 if (!swap_interval_zero_) {
1665 *out_retire_fence = layer_stack_.retire_fence;
Pullakavi Srinivas0a1dba62018-07-02 15:49:11 +05301666 }
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001667
Pullakavi Srinivas0a1dba62018-07-02 15:49:11 +05301668 if (dump_frame_count_) {
1669 dump_frame_count_--;
1670 dump_frame_index_++;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001671 }
Naseer Ahmedab06a8a2016-07-18 18:39:28 -04001672
Sushil Chauhanec4eb572019-02-07 13:29:42 -08001673 layer_stack_.flags.geometry_changed = false;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001674 geometry_changes_ = GeometryChanges::kNone;
1675 flush_ = false;
Padmanabhan Komandurue74cf4f2019-04-25 17:38:43 -07001676 skip_commit_ = false;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001677
1678 return status;
1679}
1680
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001681void HWCDisplay::SetIdleTimeoutMs(uint32_t timeout_ms) {
1682 return;
1683}
1684
1685DisplayError HWCDisplay::SetMaxMixerStages(uint32_t max_mixer_stages) {
1686 DisplayError error = kErrorNone;
1687
1688 if (display_intf_) {
1689 error = display_intf_->SetMaxMixerStages(max_mixer_stages);
Saurabh Shaha307e8c2017-09-28 18:05:40 -07001690 validated_ = false;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001691 }
1692
1693 return error;
1694}
1695
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001696void HWCDisplay::DumpInputBuffers() {
1697 char dir_path[PATH_MAX];
Gurpreet Singh Dhami5713ad32018-06-08 11:49:10 -04001698 int status;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001699
1700 if (!dump_frame_count_ || flush_ || !dump_input_layers_) {
1701 return;
1702 }
1703
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +05301704 DLOGI("dump_frame_count %d dump_input_layers %d", dump_frame_count_, dump_input_layers_);
Mathew Joseph Karimpanal0a2fff52018-10-17 12:11:07 +05301705 snprintf(dir_path, sizeof(dir_path), "%s/frame_dump_disp_id_%02u_%s", HWCDebugHandler::DumpDir(),
1706 UINT32(id_), GetDisplayString());
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001707
Gurpreet Singh Dhami5713ad32018-06-08 11:49:10 -04001708 status = mkdir(dir_path, 777);
1709 if ((status != 0) && errno != EEXIST) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001710 DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
1711 return;
1712 }
1713
Gurpreet Singh Dhami5713ad32018-06-08 11:49:10 -04001714 // Even if directory exists already, need to explicitly change the permission.
1715 if (chmod(dir_path, 0777) != 0) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001716 DLOGW("Failed to change permissions on %s directory", dir_path);
1717 return;
1718 }
1719
1720 for (uint32_t i = 0; i < layer_stack_.layers.size(); i++) {
1721 auto layer = layer_stack_.layers.at(i);
1722 const private_handle_t *pvt_handle =
Arun Kumar K.R9c19cdd2016-11-21 16:48:43 -08001723 reinterpret_cast<const private_handle_t *>(layer->input_buffer.buffer_id);
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05301724 Fence::Wait(layer->input_buffer.acquire_fence);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001725
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +05301726 DLOGI("Dump layer[%d] of %d pvt_handle %x pvt_handle->base %x", i, layer_stack_.layers.size(),
1727 pvt_handle, pvt_handle? pvt_handle->base : 0);
1728
Uday Kiran Pichika2ba46dc2017-10-26 11:15:29 +05301729 if (!pvt_handle) {
1730 DLOGE("Buffer handle is null");
Ramakant Singh6c749322018-11-24 16:32:23 +05301731 continue;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001732 }
Uday Kiran Pichika2ba46dc2017-10-26 11:15:29 +05301733
1734 if (!pvt_handle->base) {
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05301735 DisplayError error = buffer_allocator_->MapBuffer(pvt_handle, nullptr);
Uday Kiran Pichika2ba46dc2017-10-26 11:15:29 +05301736 if (error != kErrorNone) {
1737 DLOGE("Failed to map buffer, error = %d", error);
Ramakant Singh6c749322018-11-24 16:32:23 +05301738 continue;
Uday Kiran Pichika2ba46dc2017-10-26 11:15:29 +05301739 }
1740 }
1741
1742 char dump_file_name[PATH_MAX];
1743 size_t result = 0;
1744
1745 snprintf(dump_file_name, sizeof(dump_file_name), "%s/input_layer%d_%dx%d_%s_frame%d.raw",
1746 dir_path, i, pvt_handle->width, pvt_handle->height,
1747 qdutils::GetHALPixelFormatString(pvt_handle->format), dump_frame_index_);
1748
1749 FILE *fp = fopen(dump_file_name, "w+");
1750 if (fp) {
1751 result = fwrite(reinterpret_cast<void *>(pvt_handle->base), pvt_handle->size, 1, fp);
1752 fclose(fp);
1753 }
1754
1755 int release_fence = -1;
1756 DisplayError error = buffer_allocator_->UnmapBuffer(pvt_handle, &release_fence);
1757 if (error != kErrorNone) {
1758 DLOGE("Failed to unmap buffer, error = %d", error);
Ramakant Singh6c749322018-11-24 16:32:23 +05301759 continue;
Uday Kiran Pichika2ba46dc2017-10-26 11:15:29 +05301760 }
1761
1762 DLOGI("Frame Dump %s: is %s", dump_file_name, result ? "Successful" : "Failed");
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001763 }
1764}
1765
Dileep Marchyaad668432019-12-02 10:44:52 +05301766void HWCDisplay::DumpOutputBuffer(const BufferInfo &buffer_info, void *base,
1767 shared_ptr<Fence> &retire_fence) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001768 char dir_path[PATH_MAX];
Gurpreet Singh Dhami5713ad32018-06-08 11:49:10 -04001769 int status;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001770
Mathew Joseph Karimpanal0a2fff52018-10-17 12:11:07 +05301771 snprintf(dir_path, sizeof(dir_path), "%s/frame_dump_disp_id_%02u_%s", HWCDebugHandler::DumpDir(),
1772 UINT32(id_), GetDisplayString());
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001773
Gurpreet Singh Dhami5713ad32018-06-08 11:49:10 -04001774 status = mkdir(dir_path, 777);
1775 if ((status != 0) && errno != EEXIST) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001776 DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
1777 return;
1778 }
1779
Gurpreet Singh Dhami5713ad32018-06-08 11:49:10 -04001780 // Even if directory exists already, need to explicitly change the permission.
1781 if (chmod(dir_path, 0777) != 0) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001782 DLOGW("Failed to change permissions on %s directory", dir_path);
1783 return;
1784 }
1785
1786 if (base) {
1787 char dump_file_name[PATH_MAX];
1788 size_t result = 0;
1789
Dileep Marchyaad668432019-12-02 10:44:52 +05301790 if (Fence::Wait(retire_fence) != kErrorNone) {
1791 DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
1792 return;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001793 }
1794
1795 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 -04001796 dir_path, buffer_info.alloc_buffer_info.aligned_width,
1797 buffer_info.alloc_buffer_info.aligned_height,
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001798 GetFormatString(buffer_info.buffer_config.format), dump_frame_index_);
1799
1800 FILE *fp = fopen(dump_file_name, "w+");
1801 if (fp) {
1802 result = fwrite(base, buffer_info.alloc_buffer_info.size, 1, fp);
1803 fclose(fp);
1804 }
1805
1806 DLOGI("Frame Dump of %s is %s", dump_file_name, result ? "Successful" : "Failed");
1807 }
1808}
1809
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001810const char *HWCDisplay::GetDisplayString() {
1811 switch (type_) {
Mathew Joseph Karimpanal0a2fff52018-10-17 12:11:07 +05301812 case kBuiltIn:
1813 return "builtin";
1814 case kPluggable:
1815 return "pluggable";
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001816 case kVirtual:
1817 return "virtual";
1818 default:
1819 return "invalid";
1820 }
1821}
1822
Padmanabhan Komandurua4bf6062019-10-13 09:04:49 +05301823int HWCDisplay::SetFrameBufferConfig(uint32_t x_pixels, uint32_t y_pixels) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001824 if (x_pixels <= 0 || y_pixels <= 0) {
Naseer Ahmed42fc8d12016-05-11 18:33:57 -04001825 DLOGW("Unsupported config: x_pixels=%d, y_pixels=%d", x_pixels, y_pixels);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001826 return -EINVAL;
1827 }
1828
Arun Kumar K.R8da7f502016-06-07 17:45:50 -07001829 DisplayConfigVariableInfo fb_config;
1830 DisplayError error = display_intf_->GetFrameBufferConfig(&fb_config);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001831 if (error != kErrorNone) {
Arun Kumar K.R8da7f502016-06-07 17:45:50 -07001832 DLOGV("Get frame buffer config failed. Error = %d", error);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001833 return -EINVAL;
1834 }
1835
Arun Kumar K.R8da7f502016-06-07 17:45:50 -07001836 fb_config.x_pixels = x_pixels;
1837 fb_config.y_pixels = y_pixels;
1838
1839 error = display_intf_->SetFrameBufferConfig(fb_config);
1840 if (error != kErrorNone) {
1841 DLOGV("Set frame buffer config failed. Error = %d", error);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001842 return -EINVAL;
1843 }
1844
1845 // Create rects to represent the new source and destination crops
1846 LayerRect crop = LayerRect(0, 0, FLOAT(x_pixels), FLOAT(y_pixels));
Ramakant Singh830e9852017-07-29 21:31:09 +05301847 hwc_rect_t scaled_display_frame = {0, 0, INT(x_pixels), INT(y_pixels)};
Padmanabhan Komandurua4bf6062019-10-13 09:04:49 +05301848 auto client_target_layer = client_target_->GetSDMLayer();
1849 client_target_layer->src_rect = crop;
Ramakant Singh830e9852017-07-29 21:31:09 +05301850 ApplyScanAdjustment(&scaled_display_frame);
1851 client_target_->SetLayerDisplayFrame(scaled_display_frame);
1852 client_target_->ResetPerFrameData();
1853
Padmanabhan Komandurua4bf6062019-10-13 09:04:49 +05301854 DLOGI("New framebuffer resolution (%dx%d)", fb_config.x_pixels, fb_config.y_pixels);
1855
1856 return 0;
1857}
1858
1859int HWCDisplay::SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels) {
1860 int error = SetFrameBufferConfig(x_pixels, y_pixels);
1861 if (error < 0) {
1862 DLOGV("SetFrameBufferConfig failed. Error = %d", error);
1863 return error;
1864 }
1865
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001866 auto client_target_layer = client_target_->GetSDMLayer();
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001867
1868 int aligned_width;
1869 int aligned_height;
Naseer Ahmed42752212017-01-27 17:32:21 -05001870 uint32_t usage = GRALLOC_USAGE_HW_FB;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001871 int format = HAL_PIXEL_FORMAT_RGBA_8888;
Prabhanjan Kandula9e3df622017-07-27 12:35:09 -07001872 int ubwc_disabled = 0;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001873 int flags = 0;
Prabhanjan Kandula9e3df622017-07-27 12:35:09 -07001874
1875 // By default UBWC is enabled and below property is global enable/disable for all
1876 // buffers allocated through gralloc , including framebuffer targets.
Uday Kiran Pichika5e656b22018-05-15 18:48:24 +05301877 HWCDebugHandler::Get()->GetProperty(DISABLE_UBWC_PROP, &ubwc_disabled);
Prabhanjan Kandula9e3df622017-07-27 12:35:09 -07001878 if (!ubwc_disabled) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001879 usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
1880 flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
1881 }
Naseer Ahmed42752212017-01-27 17:32:21 -05001882
Naseer Ahmed42752212017-01-27 17:32:21 -05001883 buffer_allocator_->GetAlignedWidthAndHeight(INT(x_pixels), INT(y_pixels), format, usage,
1884 &aligned_width, &aligned_height);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001885
1886 // TODO(user): How does the dirty region get set on the client target? File bug on Google
1887 client_target_layer->composition = kCompositionGPUTarget;
Gousemoodhin Nadafa990d722018-04-04 08:33:43 +05301888 client_target_layer->input_buffer.format = HWCLayer::GetSDMFormat(format, flags);
Arun Kumar K.R9c19cdd2016-11-21 16:48:43 -08001889 client_target_layer->input_buffer.width = UINT32(aligned_width);
1890 client_target_layer->input_buffer.height = UINT32(aligned_height);
1891 client_target_layer->input_buffer.unaligned_width = x_pixels;
1892 client_target_layer->input_buffer.unaligned_height = y_pixels;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001893 client_target_layer->plane_alpha = 255;
1894
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001895 return 0;
1896}
1897
1898void HWCDisplay::GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
Arun Kumar K.R8da7f502016-06-07 17:45:50 -07001899 DisplayConfigVariableInfo fb_config;
1900 display_intf_->GetFrameBufferConfig(&fb_config);
1901
1902 *x_pixels = fb_config.x_pixels;
1903 *y_pixels = fb_config.y_pixels;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001904}
1905
Arun Kumar K.R8da7f502016-06-07 17:45:50 -07001906DisplayError HWCDisplay::GetMixerResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
1907 return display_intf_->GetMixerResolution(x_pixels, y_pixels);
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001908}
1909
1910void HWCDisplay::GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
Arun Kumar K.R8da7f502016-06-07 17:45:50 -07001911 DisplayConfigVariableInfo display_config;
1912 uint32_t active_index = 0;
1913
1914 display_intf_->GetActiveConfig(&active_index);
1915 display_intf_->GetConfig(active_index, &display_config);
1916
1917 *x_pixels = display_config.x_pixels;
1918 *y_pixels = display_config.y_pixels;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001919}
1920
Dileep Marchya6860b2b2017-04-07 15:56:47 +05301921int HWCDisplay::SetDisplayStatus(DisplayStatus display_status) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001922 int status = 0;
1923
1924 switch (display_status) {
1925 case kDisplayStatusResume:
1926 display_paused_ = false;
Anjaneya Prasad Musunuri7a509c12018-11-15 15:54:42 +05301927 status = INT32(SetPowerMode(HWC2::PowerMode::On, false /* teardown */));
1928 break;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001929 case kDisplayStatusOnline:
Varun Arora78580b82018-09-10 13:59:57 -07001930 status = INT32(SetPowerMode(HWC2::PowerMode::On, false /* teardown */));
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001931 break;
1932 case kDisplayStatusPause:
1933 display_paused_ = true;
Anjaneya Prasad Musunuri7a509c12018-11-15 15:54:42 +05301934 status = INT32(SetPowerMode(HWC2::PowerMode::Off, false /* teardown */));
1935 break;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001936 case kDisplayStatusOffline:
Varun Arora78580b82018-09-10 13:59:57 -07001937 status = INT32(SetPowerMode(HWC2::PowerMode::Off, false /* teardown */));
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001938 break;
1939 default:
1940 DLOGW("Invalid display status %d", display_status);
1941 return -EINVAL;
1942 }
1943
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001944 return status;
1945}
1946
1947HWC2::Error HWCDisplay::SetCursorPosition(hwc2_layer_t layer, int x, int y) {
1948 if (shutdown_pending_) {
1949 return HWC2::Error::None;
1950 }
1951
Anjaneya Prasad Musunuri3f974b42018-05-10 15:31:58 +05301952 if (!layer_stack_.flags.cursor_present) {
1953 DLOGW("Cursor layer not present");
1954 return HWC2::Error::BadLayer;
1955 }
1956
Arun Kumar K.R1018d5b2017-06-08 13:51:05 +05301957 HWCLayer *hwc_layer = GetHWCLayer(layer);
1958 if (hwc_layer == nullptr) {
Naseer Ahmedb1e8ea92017-04-18 21:17:34 -04001959 return HWC2::Error::BadLayer;
1960 }
Arun Kumar K.R1018d5b2017-06-08 13:51:05 +05301961 if (hwc_layer->GetDeviceSelectedCompositionType() != HWC2::Composition::Cursor) {
1962 return HWC2::Error::None;
1963 }
Sushil Chauhane3a9fd02017-10-12 18:00:05 -07001964 if ((validate_state_ != kSkipValidate) && validated_) {
Arun Kumar K.R1018d5b2017-06-08 13:51:05 +05301965 // the device is currently in the middle of the validate/present sequence,
1966 // cannot set the Position(as per HWC2 spec)
1967 return HWC2::Error::NotValidated;
1968 }
Naseer Ahmedb1e8ea92017-04-18 21:17:34 -04001969
1970 DisplayState state;
1971 if (display_intf_->GetDisplayState(&state) == kErrorNone) {
1972 if (state != kStateOn) {
1973 return HWC2::Error::None;
1974 }
1975 }
1976
Arun Kumar K.R1018d5b2017-06-08 13:51:05 +05301977 // TODO(user): HWC1.5 was not letting SetCursorPosition before validateDisplay,
1978 // but HWC2.0 doesn't let setting cursor position after validate before present.
1979 // Need to revisit.
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001980
1981 auto error = display_intf_->SetCursorPosition(x, y);
1982 if (error != kErrorNone) {
1983 if (error == kErrorShutDown) {
1984 shutdown_pending_ = true;
1985 return HWC2::Error::None;
1986 }
1987
1988 DLOGE("Failed for x = %d y = %d, Error = %d", x, y, error);
1989 return HWC2::Error::BadDisplay;
1990 }
1991
1992 return HWC2::Error::None;
1993}
1994
1995int HWCDisplay::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
1996 DisplayError error = display_intf_->OnMinHdcpEncryptionLevelChange(min_enc_level);
1997 if (error != kErrorNone) {
1998 DLOGE("Failed. Error = %d", error);
1999 return -1;
2000 }
2001
Saurabh Shaha307e8c2017-09-28 18:05:40 -07002002 validated_ = false;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002003 return 0;
2004}
2005
2006void HWCDisplay::MarkLayersForGPUBypass() {
2007 for (auto hwc_layer : layer_set_) {
2008 auto layer = hwc_layer->GetSDMLayer();
2009 layer->composition = kCompositionSDE;
2010 }
Saurabh Shaha307e8c2017-09-28 18:05:40 -07002011 validated_ = true;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002012}
2013
Arun Kumar K.R29cd6582016-05-10 19:12:45 -07002014void HWCDisplay::MarkLayersForClientComposition() {
2015 // ClientComposition - GPU comp, to acheive this, set skip flag so that
2016 // SDM does not handle this layer and hwc_layer composition will be
2017 // set correctly at the end of Prepare.
Saurabh Dubeyd90a6a42017-10-24 16:28:01 +05302018 DLOGV_IF(kTagClient, "HWC Layers marked for GPU comp");
Arun Kumar K.R29cd6582016-05-10 19:12:45 -07002019 for (auto hwc_layer : layer_set_) {
2020 Layer *layer = hwc_layer->GetSDMLayer();
2021 layer->flags.skip = true;
2022 }
Naseer Ahmed738da072018-01-24 14:41:46 -05002023 layer_stack_.flags.skip_present = true;
Arun Kumar K.R29cd6582016-05-10 19:12:45 -07002024}
2025
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002026void HWCDisplay::ApplyScanAdjustment(hwc_rect_t *display_frame) {
2027}
2028
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002029int HWCDisplay::ToggleScreenUpdates(bool enable) {
2030 display_paused_ = enable ? false : true;
Padmanabhan Komandurue74cf4f2019-04-25 17:38:43 -07002031 callbacks_->Refresh(id_);
Saurabh Shaha307e8c2017-09-28 18:05:40 -07002032 validated_ = false;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002033 return 0;
2034}
2035
2036int HWCDisplay::ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
2037 PPDisplayAPIPayload *out_payload,
2038 PPPendingParams *pending_action) {
2039 int ret = 0;
2040
2041 if (display_intf_)
2042 ret = display_intf_->ColorSVCRequestRoute(in_payload, out_payload, pending_action);
2043 else
2044 ret = -EINVAL;
2045
2046 return ret;
2047}
2048
Arun Kumar K.R536c7d62016-06-14 18:47:39 -07002049void HWCDisplay::SolidFillPrepare() {
2050 if (solid_fill_enable_) {
2051 if (solid_fill_layer_ == NULL) {
2052 // Create a dummy layer here
2053 solid_fill_layer_ = new Layer();
Arun Kumar K.R536c7d62016-06-14 18:47:39 -07002054 }
2055 uint32_t primary_width = 0, primary_height = 0;
2056 GetMixerResolution(&primary_width, &primary_height);
2057
Arun Kumar K.R9c19cdd2016-11-21 16:48:43 -08002058 LayerBuffer *layer_buffer = &solid_fill_layer_->input_buffer;
Arun Kumar K.R536c7d62016-06-14 18:47:39 -07002059 layer_buffer->width = primary_width;
2060 layer_buffer->height = primary_height;
Ramkumar Radhakrishnanb27735f2016-08-26 22:37:23 -07002061 layer_buffer->unaligned_width = primary_width;
2062 layer_buffer->unaligned_height = primary_height;
Arun Kumar K.R536c7d62016-06-14 18:47:39 -07002063
Arun Kumar K.R536c7d62016-06-14 18:47:39 -07002064 solid_fill_layer_->composition = kCompositionGPU;
Gopikrishnaiah Anandanb032efb2017-08-30 12:49:46 -07002065 solid_fill_layer_->src_rect = solid_fill_rect_;
2066 solid_fill_layer_->dst_rect = solid_fill_rect_;
Arun Kumar K.R536c7d62016-06-14 18:47:39 -07002067
2068 solid_fill_layer_->blending = kBlendingPremultiplied;
Gopikrishnaiah Anandancc123062017-07-31 17:21:03 -07002069 solid_fill_layer_->solid_fill_color = 0;
2070 solid_fill_layer_->solid_fill_info.bit_depth = solid_fill_color_.bit_depth;
2071 solid_fill_layer_->solid_fill_info.red = solid_fill_color_.red;
2072 solid_fill_layer_->solid_fill_info.blue = solid_fill_color_.blue;
2073 solid_fill_layer_->solid_fill_info.green = solid_fill_color_.green;
2074 solid_fill_layer_->solid_fill_info.alpha = solid_fill_color_.alpha;
Arun Kumar K.R536c7d62016-06-14 18:47:39 -07002075 solid_fill_layer_->frame_rate = 60;
2076 solid_fill_layer_->visible_regions.push_back(solid_fill_layer_->dst_rect);
2077 solid_fill_layer_->flags.updating = 1;
2078 solid_fill_layer_->flags.solid_fill = true;
2079 } else {
2080 // delete the dummy layer
Arun Kumar K.R536c7d62016-06-14 18:47:39 -07002081 delete solid_fill_layer_;
2082 solid_fill_layer_ = NULL;
2083 }
2084
2085 if (solid_fill_enable_ && solid_fill_layer_) {
2086 BuildSolidFillStack();
2087 MarkLayersForGPUBypass();
2088 }
2089
2090 return;
2091}
2092
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002093int HWCDisplay::GetVisibleDisplayRect(hwc_rect_t *visible_rect) {
2094 if (!IsValid(display_rect_)) {
2095 return -EINVAL;
2096 }
2097
2098 visible_rect->left = INT(display_rect_.left);
2099 visible_rect->top = INT(display_rect_.top);
2100 visible_rect->right = INT(display_rect_.right);
2101 visible_rect->bottom = INT(display_rect_.bottom);
2102 DLOGI("Dpy = %d Visible Display Rect(%d %d %d %d)", visible_rect->left, visible_rect->top,
2103 visible_rect->right, visible_rect->bottom);
2104
2105 return 0;
2106}
2107
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -07002108int HWCDisplay::HandleSecureSession(const std::bitset<kSecureMax> &secure_sessions,
2109 bool *power_on_pending) {
2110 if (!power_on_pending) {
2111 return -EINVAL;
Ramakant Singh46a1bee2017-09-22 21:26:21 +05302112 }
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -07002113
2114 if (active_secure_sessions_[kSecureDisplay] != secure_sessions[kSecureDisplay]) {
2115 if (secure_sessions[kSecureDisplay]) {
Mathew Joseph Karimpanalb1c15862019-07-04 11:14:24 +05302116 pending_power_mode_ = current_power_mode_;
Varun Arora78580b82018-09-10 13:59:57 -07002117 HWC2::Error error = SetPowerMode(HWC2::PowerMode::Off, true /* teardown */);
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -07002118 if (error != HWC2::Error::None) {
2119 DLOGE("SetPowerMode failed. Error = %d", error);
2120 }
2121 } else {
2122 *power_on_pending = true;
2123 }
2124
Mathew Joseph Karimpanalb1c15862019-07-04 11:14:24 +05302125 DLOGI("SecureDisplay state changed from %d to %d for display %d-%d",
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -07002126 active_secure_sessions_.test(kSecureDisplay), secure_sessions.test(kSecureDisplay),
Mathew Joseph Karimpanalb1c15862019-07-04 11:14:24 +05302127 id_, type_);
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -07002128 }
2129 active_secure_sessions_ = secure_sessions;
2130 return 0;
2131}
2132
2133int HWCDisplay::GetActiveSecureSession(std::bitset<kSecureMax> *secure_sessions) {
2134 if (!secure_sessions) {
2135 return -1;
2136 }
2137 secure_sessions->reset();
2138 for (auto hwc_layer : layer_set_) {
2139 Layer *layer = hwc_layer->GetSDMLayer();
2140 if (layer->input_buffer.flags.secure_camera) {
2141 secure_sessions->set(kSecureCamera);
2142 }
2143 if (layer->input_buffer.flags.secure_display) {
2144 secure_sessions->set(kSecureDisplay);
2145 }
2146 }
2147 return 0;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002148}
2149
Dileep Marchya6860b2b2017-04-07 15:56:47 +05302150int HWCDisplay::SetActiveDisplayConfig(uint32_t config) {
Pullakavi Srinivas8b33a282018-11-01 12:45:38 +05302151 uint32_t current_config = 0;
2152 display_intf_->GetActiveConfig(&current_config);
2153 if (config == current_config) {
Ramkumar Radhakrishnan3dcf8a22017-11-27 14:53:06 -08002154 return 0;
2155 }
Ramkumar Radhakrishnan3dcf8a22017-11-27 14:53:06 -08002156
Pullakavi Srinivas8b33a282018-11-01 12:45:38 +05302157 validated_ = false;
2158 display_intf_->SetActiveConfig(config);
Ramkumar Radhakrishnan3dcf8a22017-11-27 14:53:06 -08002159
2160 return 0;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002161}
2162
2163int HWCDisplay::GetActiveDisplayConfig(uint32_t *config) {
2164 return display_intf_->GetActiveConfig(config) == kErrorNone ? 0 : -1;
2165}
2166
2167int HWCDisplay::GetDisplayConfigCount(uint32_t *count) {
2168 return display_intf_->GetNumVariableInfoConfigs(count) == kErrorNone ? 0 : -1;
2169}
2170
Arun Kumar K.R8da7f502016-06-07 17:45:50 -07002171int HWCDisplay::GetDisplayAttributesForConfig(int config,
2172 DisplayConfigVariableInfo *display_attributes) {
2173 return display_intf_->GetConfig(UINT32(config), display_attributes) == kErrorNone ? 0 : -1;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002174}
2175
Ramakant Singh5db0dfb2017-08-23 12:34:57 +05302176uint32_t HWCDisplay::GetUpdatingLayersCount(void) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002177 uint32_t updating_count = 0;
2178
Arun Kumar K.R536c7d62016-06-14 18:47:39 -07002179 for (uint i = 0; i < layer_stack_.layers.size(); i++) {
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002180 auto layer = layer_stack_.layers.at(i);
2181 if (layer->flags.updating) {
2182 updating_count++;
2183 }
2184 }
2185
Ramakant Singh5db0dfb2017-08-23 12:34:57 +05302186 return updating_count;
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002187}
2188
Sushil Chauhan9735cf82018-07-10 12:06:01 -07002189bool HWCDisplay::IsLayerUpdating(HWCLayer *hwc_layer) {
2190 auto layer = hwc_layer->GetSDMLayer();
Arun Kumar K.R3e89f792016-06-01 17:14:15 -07002191 // Layer should be considered updating if
2192 // a) layer is in single buffer mode, or
2193 // b) valid dirty_regions(android specific hint for updating status), or
2194 // c) layer stack geometry has changed (TODO(user): Remove when SDM accepts
2195 // geometry_changed as bit fields).
Sushil Chauhan9735cf82018-07-10 12:06:01 -07002196 return (layer->flags.single_buffer || hwc_layer->IsSurfaceUpdated() ||
Arun Kumar K.R3e89f792016-06-01 17:14:15 -07002197 geometry_changes_);
2198}
2199
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002200uint32_t HWCDisplay::SanitizeRefreshRate(uint32_t req_refresh_rate) {
2201 uint32_t refresh_rate = req_refresh_rate;
2202
2203 if (refresh_rate < min_refresh_rate_) {
2204 // Pick the next multiple of request which is within the range
2205 refresh_rate =
2206 (((min_refresh_rate_ / refresh_rate) + ((min_refresh_rate_ % refresh_rate) ? 1 : 0)) *
2207 refresh_rate);
2208 }
2209
2210 if (refresh_rate > max_refresh_rate_) {
2211 refresh_rate = max_refresh_rate_;
2212 }
2213
2214 return refresh_rate;
2215}
2216
2217DisplayClass HWCDisplay::GetDisplayClass() {
2218 return display_class_;
2219}
2220
Dileep Marchya58928122020-01-28 12:16:51 +05302221void HWCDisplay::Dump(std::ostringstream *os) {
2222 *os << "\n------------HWC----------------\n";
2223 *os << "HWC2 display_id: " << id_ << std::endl;
Naseer Ahmed1fd59ea2016-05-05 13:59:23 -04002224 for (auto layer : layer_set_) {
2225 auto sdm_layer = layer->GetSDMLayer();
Arun Kumar K.Rf641dff2016-06-16 13:20:02 -07002226 auto transform = sdm_layer->transform;
Dileep Marchya58928122020-01-28 12:16:51 +05302227 *os << "layer: " << std::setw(4) << layer->GetId();
2228 *os << " z: " << layer->GetZ();
2229 *os << " composition: " <<
Naseer Ahmed85ca1202017-04-18 15:31:59 -04002230 to_string(layer->GetClientRequestedCompositionType()).c_str();
Dileep Marchya58928122020-01-28 12:16:51 +05302231 *os << "/" <<
Naseer Ahmed85ca1202017-04-18 15:31:59 -04002232 to_string(layer->GetDeviceSelectedCompositionType()).c_str();
Dileep Marchya58928122020-01-28 12:16:51 +05302233 *os << " alpha: " << std::to_string(sdm_layer->plane_alpha).c_str();
2234 *os << " format: " << std::setw(22) << GetFormatString(sdm_layer->input_buffer.format);
2235 *os << " dataspace:" << std::hex << "0x" << std::setw(8) << std::setfill('0')
2236 << layer->GetLayerDataspace() << std::dec << std::setfill(' ');
2237 *os << " transform: " << transform.rotation << "/" << transform.flip_horizontal <<
Naseer Ahmed85ca1202017-04-18 15:31:59 -04002238 "/"<< transform.flip_vertical;
Dileep Marchya58928122020-01-28 12:16:51 +05302239 *os << " buffer_id: " << std::hex << "0x" << sdm_layer->input_buffer.buffer_id << std::dec;
2240 *os << " secure: " << layer->IsProtected()
2241 << std::endl;
Naseer Ahmed1fd59ea2016-05-05 13:59:23 -04002242 }
Saurabh Shah9c224a32017-11-09 12:17:44 -08002243
Gousemoodhin Nadafa08db9e2018-07-16 14:25:09 +05302244 if (has_client_composition_) {
Dileep Marchya58928122020-01-28 12:16:51 +05302245 *os << "\n---------client target---------\n";
Gousemoodhin Nadafa08db9e2018-07-16 14:25:09 +05302246 auto sdm_layer = client_target_->GetSDMLayer();
Dileep Marchya58928122020-01-28 12:16:51 +05302247 *os << "format: " << std::setw(14) << GetFormatString(sdm_layer->input_buffer.format);
2248 *os << " dataspace:" << std::hex << "0x" << std::setw(8) << std::setfill('0')
2249 << client_target_->GetLayerDataspace() << std::dec << std::setfill(' ');
2250 *os << " buffer_id: " << std::hex << "0x" << sdm_layer->input_buffer.buffer_id << std::dec;
2251 *os << " secure: " << client_target_->IsProtected()
2252 << std::endl;
Gousemoodhin Nadafa08db9e2018-07-16 14:25:09 +05302253 }
2254
Saurabh Shahdccc0f42018-01-15 15:59:56 -08002255 if (layer_stack_invalid_) {
Dileep Marchya58928122020-01-28 12:16:51 +05302256 *os << "\n Layers added or removed but not reflected to SDM's layer stack yet\n";
2257 return;
Saurabh Shahdccc0f42018-01-15 15:59:56 -08002258 }
2259
Naseer Ahmed913502b2017-04-18 16:05:05 -04002260 if (color_mode_) {
Dileep Marchya58928122020-01-28 12:16:51 +05302261 *os << "\n----------Color Modes---------\n";
2262 color_mode_->Dump(os);
Naseer Ahmed913502b2017-04-18 16:05:05 -04002263 }
Saurabh Shah9c224a32017-11-09 12:17:44 -08002264
2265 if (display_intf_) {
Dileep Marchya58928122020-01-28 12:16:51 +05302266 *os << "\n------------SDM----------------\n";
2267 *os << display_intf_->Dump();
Saurabh Shah9c224a32017-11-09 12:17:44 -08002268 }
2269
Dileep Marchya58928122020-01-28 12:16:51 +05302270 *os << "\n";
Naseer Ahmed1fd59ea2016-05-05 13:59:23 -04002271}
Sushil Chauhan409e8442017-06-12 17:43:25 -07002272
2273bool HWCDisplay::CanSkipValidate() {
Sushil Chauhanca302b72018-02-27 18:38:22 -08002274 if (!validated_ || solid_fill_enable_) {
Naseer Ahmed34b341d2017-10-05 18:47:15 -04002275 return false;
2276 }
2277
Saurabh Dubey66b807e2018-05-11 10:05:07 +05302278 if ((tone_mapper_ && tone_mapper_->IsActive()) ||
Arun Kumar K.R2a419be2018-04-27 12:43:58 +05302279 layer_stack_.flags.single_buffered_layer_present) {
Saurabh Dubey66b807e2018-05-11 10:05:07 +05302280 DLOGV_IF(kTagClient, "Tonemapping enabled or single buffer layer present = %d"
2281 " Returning false.", layer_stack_.flags.single_buffered_layer_present);
Sushil Chauhan409e8442017-06-12 17:43:25 -07002282 return false;
2283 }
2284
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +05302285 if (client_target_->NeedsValidation()) {
Saurabh Dubeyd90a6a42017-10-24 16:28:01 +05302286 DLOGV_IF(kTagClient, "Framebuffer target needs validation. Returning false.");
Arun Kumar K.R80e58eb2017-07-13 10:37:00 +05302287 return false;
2288 }
2289
Sushil Chauhan409e8442017-06-12 17:43:25 -07002290 for (auto hwc_layer : layer_set_) {
Ramkumar Radhakrishnan1a31bc22018-08-23 14:42:05 -07002291 Layer *layer = hwc_layer->GetSDMLayer();
Sushil Chauhan409e8442017-06-12 17:43:25 -07002292 if (hwc_layer->NeedsValidation()) {
Saurabh Dubeyd90a6a42017-10-24 16:28:01 +05302293 DLOGV_IF(kTagClient, "hwc_layer[%d] needs validation. Returning false.",
2294 hwc_layer->GetId());
Sushil Chauhan409e8442017-06-12 17:43:25 -07002295 return false;
2296 }
2297
2298 // Do not allow Skip Validate, if any layer needs GPU Composition.
Ramkumar Radhakrishnan1a31bc22018-08-23 14:42:05 -07002299 if (layer->composition == kCompositionGPU || layer->composition == kCompositionNone) {
2300 DLOGV_IF(kTagClient, "hwc_layer[%d] is %s. Returning false.", hwc_layer->GetId(),
2301 (layer->composition == kCompositionGPU) ? "GPU composed": "Dropped");
Sushil Chauhan409e8442017-06-12 17:43:25 -07002302 return false;
2303 }
2304 }
2305
Pullakavi Srinivasad8bd012019-04-22 17:04:51 +05302306 if (!layer_set_.empty() && !display_intf_->CanSkipValidate()) {
2307 return false;
2308 }
2309
Sushil Chauhan409e8442017-06-12 17:43:25 -07002310 return true;
2311}
2312
Sushil Chauhane3a9fd02017-10-12 18:00:05 -07002313HWC2::Error HWCDisplay::GetValidateDisplayOutput(uint32_t *out_num_types,
2314 uint32_t *out_num_requests) {
2315 *out_num_types = UINT32(layer_changes_.size());
2316 *out_num_requests = UINT32(layer_requests_.size());
2317
2318 return ((*out_num_types > 0) ? HWC2::Error::HasChanges : HWC2::Error::None);
2319}
2320
Varun Arora6ba9eda2019-02-07 17:59:32 -08002321HWC2::Error HWCDisplay::GetDisplayIdentificationData(uint8_t *out_port, uint32_t *out_data_size,
2322 uint8_t *out_data) {
2323 DisplayError ret = display_intf_->GetDisplayIdentificationData(out_port, out_data_size, out_data);
2324 if (ret != kErrorNone) {
Pullakavi Srinivasf2a31852019-04-23 14:32:08 -07002325 DLOGE("Failed due to SDM/Driver (err = %d, disp id = %" PRIu64
Varun Arora6ba9eda2019-02-07 17:59:32 -08002326 " %d-%d", ret, id_, sdm_id_, type_);
2327 }
Pullakavi Srinivasf2a31852019-04-23 14:32:08 -07002328
Varun Arora6ba9eda2019-02-07 17:59:32 -08002329 return HWC2::Error::None;
2330}
2331
Padmanabhan Komanduru13b5e102019-12-03 12:35:09 +05302332HWC2::Error HWCDisplay::SetDisplayElapseTime(uint64_t time) {
2333 elapse_timestamp_ = time;
2334 return HWC2::Error::None;
2335}
2336
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -07002337bool HWCDisplay::IsDisplayCommandMode() {
Tharaga Balachandran04192a62018-08-29 16:23:25 -04002338 return is_cmd_mode_;
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -07002339}
2340
Lakshmi Narayana Kalavala25fe12c2019-12-11 20:44:55 -08002341HWC2::Error HWCDisplay::SetDisplayedContentSamplingEnabledVndService(bool enabled) {
2342 return HWC2::Error::Unsupported;
2343}
2344
2345HWC2::Error HWCDisplay::SetDisplayedContentSamplingEnabled(int32_t enabled, uint8_t component_mask,
2346 uint64_t max_frames) {
2347 DLOGV("Request to start/stop histogram thread not supported on this display");
2348 return HWC2::Error::Unsupported;
2349}
2350
2351HWC2::Error HWCDisplay::GetDisplayedContentSamplingAttributes(int32_t *format, int32_t *dataspace,
2352 uint8_t *supported_components) {
2353 return HWC2::Error::Unsupported;
2354}
2355
2356HWC2::Error HWCDisplay::GetDisplayedContentSample(
2357 uint64_t max_frames, uint64_t timestamp, uint64_t *numFrames,
2358 int32_t samples_size[NUM_HISTOGRAM_COLOR_COMPONENTS],
2359 uint64_t *samples[NUM_HISTOGRAM_COLOR_COMPONENTS]) {
2360 return HWC2::Error::Unsupported;
2361}
2362
Sushil Chauhan36c059a2018-06-28 11:39:01 -07002363// Skip SDM prepare if all the layers in the current draw cycle are marked as Skip and
2364// previous draw cycle had GPU Composition, as the resources for GPU Target layer have
2365// already been validated and configured to the driver.
2366bool HWCDisplay::CanSkipSdmPrepare(uint32_t *num_types, uint32_t *num_requests) {
2367 if (!validated_ || layer_set_.empty()) {
2368 return false;
2369 }
2370
2371 bool skip_prepare = true;
2372 for (auto hwc_layer : layer_set_) {
2373 if (!hwc_layer->GetSDMLayer()->flags.skip ||
2374 (hwc_layer->GetDeviceSelectedCompositionType() != HWC2::Composition::Client)) {
2375 skip_prepare = false;
2376 layer_changes_.clear();
2377 break;
2378 }
2379 if (hwc_layer->GetClientRequestedCompositionType() != HWC2::Composition::Client) {
2380 layer_changes_[hwc_layer->GetId()] = HWC2::Composition::Client;
2381 }
2382 }
2383
2384 if (skip_prepare) {
2385 *num_types = UINT32(layer_changes_.size());
2386 *num_requests = 0;
2387 layer_stack_invalid_ = false;
2388 has_client_composition_ = true;
2389 client_target_->ResetValidation();
2390 validate_state_ = kNormalValidate;
2391 }
2392
2393 return skip_prepare;
2394}
2395
Pullakavi Srinivas3dbb0d92018-03-07 15:15:14 +05302396void HWCDisplay::UpdateRefreshRate() {
2397 for (auto hwc_layer : layer_set_) {
2398 if (hwc_layer->HasMetaDataRefreshRate()) {
2399 continue;
2400 }
2401 auto layer = hwc_layer->GetSDMLayer();
Mahesh Aiaf3a1f992019-01-16 13:07:42 -08002402 layer->frame_rate = std::min(current_refresh_rate_, HWCDisplay::GetThrottlingRefreshRate());
Pullakavi Srinivas3dbb0d92018-03-07 15:15:14 +05302403 }
2404}
2405
Arun Kumar K.R5b821552018-12-07 08:00:15 +05302406int32_t HWCDisplay::SetClientTargetDataSpace(int32_t dataspace) {
2407 if (client_target_->GetLayerDataspace() != dataspace) {
2408 client_target_->SetLayerDataspace(dataspace);
2409 Layer *sdm_layer = client_target_->GetSDMLayer();
2410 // Data space would be validated at GetClientTargetSupport, so just use here.
2411 sdm::GetSDMColorSpace(client_target_->GetLayerDataspace(),
2412 &sdm_layer->input_buffer.color_metadata);
2413 }
2414
2415 return 0;
2416}
2417
Rajavenu Kyathamaf26f402019-02-13 15:04:03 +05302418void HWCDisplay::WaitOnPreviousFence() {
2419 DisplayConfigFixedInfo display_config;
2420 display_intf_->GetConfig(&display_config);
2421 if (!display_config.is_cmdmode) {
2422 return;
2423 }
2424
2425 // Since prepare failed commit would follow the same.
2426 // Wait for previous rel fence.
2427 for (auto hwc_layer : layer_set_) {
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05302428 shared_ptr<Fence> fence = nullptr;
2429
2430 hwc_layer->PopBackReleaseFence(&fence);
2431 if (Fence::Wait(fence) != kErrorNone) {
2432 DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
2433 return;
Rajavenu Kyathamaf26f402019-02-13 15:04:03 +05302434 }
2435 hwc_layer->PushBackReleaseFence(fence);
2436 }
Rajavenu Kyatham9d509582019-02-13 15:29:55 +05302437
Rajavenu Kyatham7338b9e2019-12-30 19:52:16 +05302438 if (Fence::Wait(fbt_release_fence_) != kErrorNone) {
2439 DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
2440 return;
Rajavenu Kyatham9d509582019-02-13 15:29:55 +05302441 }
Rajavenu Kyathamaf26f402019-02-13 15:04:03 +05302442}
2443
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +05302444void HWCDisplay::GetLayerStack(HWCLayerStack *stack) {
2445 stack->client_target = client_target_;
2446 stack->layer_map = layer_map_;
2447 stack->layer_set = layer_set_;
2448}
2449
2450void HWCDisplay::SetLayerStack(HWCLayerStack *stack) {
2451 client_target_ = stack->client_target;
2452 layer_map_ = stack->layer_map;
2453 layer_set_ = stack->layer_set;
2454}
2455
Padmanabhan Komanduruf5b7f992019-07-08 13:33:44 +05302456bool HWCDisplay::CheckResourceState() {
2457 if (display_intf_) {
2458 return display_intf_->CheckResourceState();
2459 }
2460
2461 return false;
2462}
2463
Pullakavi Srinivas81fee962019-07-26 15:49:32 +05302464void HWCDisplay::UpdateActiveConfig() {
2465 if (!pending_config_) {
2466 return;
2467 }
2468
2469 DisplayError error = display_intf_->SetActiveConfig(pending_config_index_);
2470 if (error != kErrorNone) {
2471 DLOGI("Failed to set %d config", INT(pending_config_index_));
2472 }
2473
2474 // Reset pending config.
2475 pending_config_ = false;
2476}
2477
Sushil Chauhanf8541202020-02-03 23:14:36 -08002478int32_t HWCDisplay::GetDisplayConfigGroup(DisplayConfigGroupInfo variable_config) {
2479 for (auto &config : variable_config_map_) {
2480 DisplayConfigGroupInfo const &group_info = config.second;
2481 if (group_info == variable_config) {
2482 return INT32(config.first);
2483 }
2484 }
2485
2486 return -1;
2487}
2488
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05002489} // namespace sdm