1 /*
2 * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <cutils/properties.h>
31 #include <sync/sync.h>
32 #include <utils/constants.h>
33 #include <utils/debug.h>
34 #include <utils/utils.h>
35 #include <stdarg.h>
36 #include <sys/mman.h>
37
38 #include <map>
39 #include <string>
40 #include <vector>
41
42 #include "hwc_display_builtin.h"
43 #include "hwc_debugger.h"
44 #include "hwc_session.h"
45
46 #define __CLASS__ "HWCDisplayBuiltIn"
47
48 namespace sdm {
49
Init()50 DisplayError HWCDisplayBuiltIn::PMICInterface::Init() {
51 std::string str_lcd_bias("/sys/class/lcd_bias/secure_mode");
52 fd_lcd_bias_ = ::open(str_lcd_bias.c_str(), O_WRONLY);
53 if (fd_lcd_bias_ < 0) {
54 DLOGW("File '%s' could not be opened. errno = %d, desc = %s", str_lcd_bias.c_str(), errno,
55 strerror(errno));
56 return kErrorHardware;
57 }
58
59 std::string str_leds_wled("/sys/class/leds/wled/secure_mode");
60 fd_wled_ = ::open(str_leds_wled.c_str(), O_WRONLY);
61 if (fd_wled_ < 0) {
62 DLOGW("File '%s' could not be opened. errno = %d, desc = %s", str_leds_wled.c_str(), errno,
63 strerror(errno));
64 return kErrorHardware;
65 }
66
67 return kErrorNone;
68 }
69
Deinit()70 void HWCDisplayBuiltIn::PMICInterface::Deinit() {
71 ::close(fd_lcd_bias_);
72 ::close(fd_wled_);
73 }
74
Notify(SecureEvent event)75 DisplayError HWCDisplayBuiltIn::PMICInterface::Notify(SecureEvent event) {
76 std::string str_event = (event == kSecureDisplayStart) ? std::to_string(1) : std::to_string(0);
77 ssize_t err = ::pwrite(fd_lcd_bias_, str_event.c_str(), str_event.length(), 0);
78 if (err <= 0) {
79 DLOGW("Write failed for lcd_bias, Error = %s", strerror(errno));
80 return kErrorHardware;
81 }
82
83 err = ::pwrite(fd_wled_, str_event.c_str(), str_event.length(), 0);
84 if (err <= 0) {
85 DLOGW("Write failed for wled, Error = %s", strerror(errno));
86 return kErrorHardware;
87 }
88
89 DLOGI("Successfully notifed about secure display %s to PMIC driver",
90 (event == kSecureDisplayStart) ? "start": "end");
91 return kErrorNone;
92 }
93
Create(CoreInterface * core_intf,BufferAllocator * buffer_allocator,HWCCallbacks * callbacks,HWCDisplayEventHandler * event_handler,qService::QService * qservice,hwc2_display_t id,int32_t sdm_id,HWCDisplay ** hwc_display)94 int HWCDisplayBuiltIn::Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
95 HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
96 qService::QService *qservice, hwc2_display_t id, int32_t sdm_id,
97 HWCDisplay **hwc_display) {
98 int status = 0;
99 uint32_t builtin_width = 0;
100 uint32_t builtin_height = 0;
101
102 HWCDisplay *hwc_display_builtin =
103 new HWCDisplayBuiltIn(core_intf, buffer_allocator, callbacks, event_handler, qservice, id,
104 sdm_id);
105 status = hwc_display_builtin->Init();
106 if (status) {
107 delete hwc_display_builtin;
108 return status;
109 }
110
111 hwc_display_builtin->GetMixerResolution(&builtin_width, &builtin_height);
112 int width = 0, height = 0;
113 HWCDebugHandler::Get()->GetProperty(FB_WIDTH_PROP, &width);
114 HWCDebugHandler::Get()->GetProperty(FB_HEIGHT_PROP, &height);
115 if (width > 0 && height > 0) {
116 builtin_width = UINT32(width);
117 builtin_height = UINT32(height);
118 }
119
120 status = hwc_display_builtin->SetFrameBufferResolution(builtin_width, builtin_height);
121 if (status) {
122 Destroy(hwc_display_builtin);
123 return status;
124 }
125
126 *hwc_display = hwc_display_builtin;
127
128 return status;
129 }
130
Destroy(HWCDisplay * hwc_display)131 void HWCDisplayBuiltIn::Destroy(HWCDisplay *hwc_display) {
132 hwc_display->Deinit();
133 delete hwc_display;
134 }
135
HWCDisplayBuiltIn(CoreInterface * core_intf,BufferAllocator * buffer_allocator,HWCCallbacks * callbacks,HWCDisplayEventHandler * event_handler,qService::QService * qservice,hwc2_display_t id,int32_t sdm_id)136 HWCDisplayBuiltIn::HWCDisplayBuiltIn(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
137 HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
138 qService::QService *qservice, hwc2_display_t id,
139 int32_t sdm_id)
140 : HWCDisplay(core_intf, buffer_allocator, callbacks, event_handler, qservice, kBuiltIn, id,
141 sdm_id, true, DISPLAY_CLASS_BUILTIN),
142 buffer_allocator_(buffer_allocator),
143 cpu_hint_(NULL) {
144 }
145
Init()146 int HWCDisplayBuiltIn::Init() {
147 cpu_hint_ = new CPUHint();
148 if (cpu_hint_->Init(static_cast<HWCDebugHandler *>(HWCDebugHandler::Get())) != kErrorNone) {
149 delete cpu_hint_;
150 cpu_hint_ = NULL;
151 }
152
153 use_metadata_refresh_rate_ = true;
154 int disable_metadata_dynfps = 0;
155 HWCDebugHandler::Get()->GetProperty(DISABLE_METADATA_DYNAMIC_FPS_PROP, &disable_metadata_dynfps);
156 if (disable_metadata_dynfps) {
157 use_metadata_refresh_rate_ = false;
158 }
159
160 int status = HWCDisplay::Init();
161 if (status) {
162 return status;
163 }
164 color_mode_ = new HWCColorMode(display_intf_);
165 color_mode_->Init();
166 HWCDebugHandler::Get()->GetProperty(ENABLE_DEFAULT_COLOR_MODE,
167 &default_mode_status_);
168
169 int optimize_refresh = 0;
170 HWCDebugHandler::Get()->GetProperty(ENABLE_OPTIMIZE_REFRESH, &optimize_refresh);
171 enable_optimize_refresh_ = (optimize_refresh == 1);
172 if (enable_optimize_refresh_) {
173 DLOGI("Drop redundant drawcycles %d", id_);
174 }
175 pmic_intf_ = new PMICInterface();
176 pmic_intf_->Init();
177
178 if (int vsyncs;
179 HWCDebugHandler::Get()->GetProperty(DEFER_FPS_FRAME_COUNT, &vsyncs) == kErrorNone) {
180 if (vsyncs > 0) {
181 HWCDisplay::SetVsyncsApplyRateChange(UINT32(vsyncs));
182 }
183 }
184
185 return status;
186 }
187
Deinit()188 int HWCDisplayBuiltIn::Deinit() {
189 int status = HWCDisplay::Deinit();
190
191 histogram.stop();
192
193 if (status) {
194 return status;
195 }
196 pmic_intf_->Deinit();
197 delete pmic_intf_;
198
199 return 0;
200 }
201
Dump()202 std::string HWCDisplayBuiltIn::Dump() {
203 return HWCDisplay::Dump() + histogram.Dump();
204 }
205
Validate(uint32_t * out_num_types,uint32_t * out_num_requests)206 HWC2::Error HWCDisplayBuiltIn::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
207 auto status = HWC2::Error::None;
208 DisplayError error = kErrorNone;
209
210 DTRACE_SCOPED();
211 if (display_paused_) {
212 MarkLayersForGPUBypass();
213 return status;
214 }
215
216 if (color_tranform_failed_) {
217 // Must fall back to client composition
218 MarkLayersForClientComposition();
219 }
220
221 // Fill in the remaining blanks in the layers and add them to the SDM layerstack
222 BuildLayerStack();
223 // Checks and replaces layer stack for solid fill
224 SolidFillPrepare();
225
226 // Apply current Color Mode and Render Intent.
227 if (color_mode_->ApplyCurrentColorModeWithRenderIntent(
228 static_cast<bool>(layer_stack_.flags.hdr_present)) != HWC2::Error::None) {
229 // Fallback to GPU Composition, if Color Mode can't be applied.
230 MarkLayersForClientComposition();
231 }
232
233 bool pending_output_dump = dump_frame_count_ && dump_output_to_file_;
234
235 if (readback_buffer_queued_ || pending_output_dump) {
236 CloseFd(&output_buffer_.release_fence_fd);
237 // RHS values were set in FrameCaptureAsync() called from a binder thread. They are picked up
238 // here in a subsequent draw round. Readback is not allowed for any secure use case.
239 readback_configured_ = !layer_stack_.flags.secure_present;
240 if (readback_configured_) {
241 DisablePartialUpdateOneFrame();
242 layer_stack_.output_buffer = &output_buffer_;
243 layer_stack_.flags.post_processed_output = post_processed_output_;
244 }
245 }
246 // Todo: relook this case
247 if (layer_stack_.flags.hdr_present != hdr_present_) {
248 error = display_intf_->ControlIdlePowerCollapse(!layer_stack_.flags.hdr_present, true);
249 hdr_present_ = layer_stack_.flags.hdr_present;
250 }
251
252 uint32_t num_updating_layers = GetUpdatingLayersCount();
253 bool one_updating_layer = (num_updating_layers == 1);
254 if (num_updating_layers != 0) {
255 ToggleCPUHint(one_updating_layer);
256 }
257
258 uint32_t refresh_rate = GetOptimalRefreshRate(one_updating_layer);
259 error = display_intf_->SetRefreshRate(refresh_rate, force_refresh_rate_);
260
261 // Get the refresh rate set.
262 display_intf_->GetRefreshRate(&refresh_rate);
263 bool vsync_source = (callbacks_->GetVsyncSource() == id_);
264
265 if (error == kErrorNone) {
266 if (vsync_source && (current_refresh_rate_ < refresh_rate)) {
267 DTRACE_BEGIN("HWC2::Vsync::Enable");
268 // Display is ramping up from idle.
269 // Client realizes need for resync upon change in config.
270 // Since we know config has changed, triggering vsync proactively
271 // can help in reducing pipeline delays to enable events.
272 SetVsyncEnabled(HWC2::Vsync::Enable);
273 DTRACE_END();
274 }
275 // On success, set current refresh rate to new refresh rate.
276 current_refresh_rate_ = refresh_rate;
277 }
278
279 if (layer_set_.empty()) {
280 // Avoid flush for Command mode panel.
281 flush_ = !client_connected_;
282 validated_ = true;
283 return status;
284 }
285
286 status = PrepareLayerStack(out_num_types, out_num_requests);
287 pending_commit_ = true;
288 return status;
289 }
290
CommitLayerStack()291 HWC2::Error HWCDisplayBuiltIn::CommitLayerStack() {
292 skip_commit_ = CanSkipCommit();
293 return HWCDisplay::CommitLayerStack();
294 }
295
CanSkipCommit()296 bool HWCDisplayBuiltIn::CanSkipCommit() {
297 if (layer_stack_invalid_) {
298 return false;
299 }
300
301 // Reject repeated drawcycle requests if it satisfies all conditions.
302 // 1. None of the layerstack attributes changed.
303 // 2. No new buffer latched.
304 // 3. No refresh request triggered by HWC.
305 // 4. This display is not source of vsync.
306 bool buffers_latched = false;
307 for (auto &hwc_layer : layer_set_) {
308 buffers_latched |= hwc_layer->BufferLatched();
309 hwc_layer->ResetBufferFlip();
310 }
311
312 bool vsync_source = (callbacks_->GetVsyncSource() == id_);
313 bool skip_commit = enable_optimize_refresh_ && !pending_commit_ && !buffers_latched &&
314 !pending_refresh_ && !vsync_source;
315 pending_refresh_ = false;
316
317 return skip_commit;
318 }
319
Present(int32_t * out_retire_fence)320 HWC2::Error HWCDisplayBuiltIn::Present(int32_t *out_retire_fence) {
321 auto status = HWC2::Error::None;
322
323 DTRACE_SCOPED();
324 ATRACE_INT("PartialUpdate", partial_update_enabled_);
325 ATRACE_INT("FastPath", layer_stack_.flags.fast_path);
326 ATRACE_INT("GeometryChanged", layer_stack_.flags.geometry_changed);
327 ATRACE_INT("NumLayers", static_cast <int32_t> (layer_stack_.layers.size()));
328 ATRACE_INT("SF_MarkedSkipLayer", HasForceClientComposition());
329 ATRACE_INT("HWC_MarkedSkipLayer", (HasClientComposition() &&
330 !HasForceClientComposition()));
331
332 if (display_paused_) {
333 DisplayError error = display_intf_->Flush(&layer_stack_);
334 validated_ = false;
335 if (error != kErrorNone) {
336 DLOGE("Flush failed. Error = %d", error);
337 }
338 } else {
339 status = CommitLayerStack();
340 if (status == HWC2::Error::None) {
341 HandleFrameOutput();
342 SolidFillCommit();
343 status = PostCommitLayerStack(out_retire_fence);
344 }
345 }
346
347 if (CC_UNLIKELY(!has_init_light_server_)) {
348 using ILight = ::hardware::google::light::V1_0::ILight;
349 hardware_ILight_ = ILight::getService();
350 if (hardware_ILight_ != nullptr) {
351 hardware_ILight_->setHbm(false);
352 } else {
353 DLOGE("failed to get vendor light service");
354 }
355
356 uint32_t panel_x, panel_y;
357 GetPanelResolution(&panel_x, &panel_y);
358 hbm_threshold_px_ = float(panel_x * panel_y) * hbm_threshold_pct_;
359 DLOGI("Configure hbm_threshold_px_ to %f", hbm_threshold_px_);
360
361 has_init_light_server_ = true;
362 }
363
364 const bool enable_hbm(hdr_largest_layer_px_ > hbm_threshold_px_);
365 if (high_brightness_mode_ != enable_hbm && hardware_ILight_ != nullptr) {
366 using ::android::hardware::light::V2_0::Status;
367 if (Status::SUCCESS == hardware_ILight_->setHbm(enable_hbm)) {
368 high_brightness_mode_ = enable_hbm;
369 } else {
370 DLOGE("failed to setHbm to %d", enable_hbm);
371 }
372 }
373
374 CloseFd(&output_buffer_.acquire_fence_fd);
375 pending_commit_ = false;
376 return status;
377 }
378
GetColorModes(uint32_t * out_num_modes,ColorMode * out_modes)379 HWC2::Error HWCDisplayBuiltIn::GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes) {
380 if (out_modes == nullptr) {
381 *out_num_modes = color_mode_->GetColorModeCount();
382 } else {
383 color_mode_->GetColorModes(out_num_modes, out_modes);
384 }
385
386 return HWC2::Error::None;
387 }
388
GetRenderIntents(ColorMode mode,uint32_t * out_num_intents,RenderIntent * out_intents)389 HWC2::Error HWCDisplayBuiltIn::GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
390 RenderIntent *out_intents) {
391 if (out_intents == nullptr) {
392 *out_num_intents = color_mode_->GetRenderIntentCount(mode);
393 } else {
394 color_mode_->GetRenderIntents(mode, out_num_intents, out_intents);
395 }
396 return HWC2::Error::None;
397 }
398
SetColorMode(ColorMode mode)399 HWC2::Error HWCDisplayBuiltIn::SetColorMode(ColorMode mode) {
400 return SetColorModeWithRenderIntent(mode, RenderIntent::COLORIMETRIC);
401 }
402
SetColorModeWithRenderIntent(ColorMode mode,RenderIntent intent)403 HWC2::Error HWCDisplayBuiltIn::SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
404 auto status = color_mode_->CacheColorModeWithRenderIntent(mode, intent);
405 if (status != HWC2::Error::None) {
406 DLOGE("failed for mode = %d intent = %d", mode, intent);
407 return status;
408 }
409 callbacks_->Refresh(id_);
410 validated_ = false;
411 return status;
412 }
413
SetColorModeById(int32_t color_mode_id)414 HWC2::Error HWCDisplayBuiltIn::SetColorModeById(int32_t color_mode_id) {
415 auto status = color_mode_->SetColorModeById(color_mode_id);
416 if (status != HWC2::Error::None) {
417 DLOGE("failed for mode = %d", color_mode_id);
418 return status;
419 }
420
421 callbacks_->Refresh(id_);
422 validated_ = false;
423
424 return status;
425 }
426
SetColorModeFromClientApi(int32_t color_mode_id)427 HWC2::Error HWCDisplayBuiltIn::SetColorModeFromClientApi(int32_t color_mode_id) {
428 DisplayError error = kErrorNone;
429 std::string mode_string;
430
431 error = display_intf_->GetColorModeName(color_mode_id, &mode_string);
432 if (error) {
433 DLOGE("Failed to get mode name for mode %d", color_mode_id);
434 return HWC2::Error::BadParameter;
435 }
436
437 auto status = color_mode_->SetColorModeFromClientApi(mode_string);
438 if (status != HWC2::Error::None) {
439 DLOGE("Failed to set mode = %d", color_mode_id);
440 return status;
441 }
442
443 return status;
444 }
445
RestoreColorTransform()446 HWC2::Error HWCDisplayBuiltIn::RestoreColorTransform() {
447 auto status = color_mode_->RestoreColorTransform();
448 if (status != HWC2::Error::None) {
449 DLOGE("failed to RestoreColorTransform");
450 return status;
451 }
452
453 callbacks_->Refresh(id_);
454
455 return status;
456 }
457
SetColorTransform(const float * matrix,android_color_transform_t hint)458 HWC2::Error HWCDisplayBuiltIn::SetColorTransform(const float *matrix,
459 android_color_transform_t hint) {
460 if (!matrix) {
461 return HWC2::Error::BadParameter;
462 }
463
464 auto status = color_mode_->SetColorTransform(matrix, hint);
465 if (status != HWC2::Error::None) {
466 DLOGE("failed for hint = %d", hint);
467 color_tranform_failed_ = true;
468 return status;
469 }
470
471 callbacks_->Refresh(id_);
472 color_tranform_failed_ = false;
473 validated_ = false;
474
475 return status;
476 }
477
SetReadbackBuffer(const native_handle_t * buffer,int32_t acquire_fence,bool post_processed_output)478 HWC2::Error HWCDisplayBuiltIn::SetReadbackBuffer(const native_handle_t *buffer,
479 int32_t acquire_fence,
480 bool post_processed_output) {
481 const private_handle_t *handle = reinterpret_cast<const private_handle_t *>(buffer);
482 if (!handle || (handle->fd < 0)) {
483 return HWC2::Error::BadParameter;
484 }
485
486 // Configure the output buffer as Readback buffer
487 output_buffer_.width = UINT32(handle->width);
488 output_buffer_.height = UINT32(handle->height);
489 output_buffer_.unaligned_width = UINT32(handle->unaligned_width);
490 output_buffer_.unaligned_height = UINT32(handle->unaligned_height);
491 output_buffer_.format = HWCLayer::GetSDMFormat(handle->format, handle->flags);
492 output_buffer_.planes[0].fd = handle->fd;
493 output_buffer_.planes[0].stride = UINT32(handle->width);
494 output_buffer_.acquire_fence_fd = dup(acquire_fence);
495 output_buffer_.release_fence_fd = -1;
496 output_buffer_.handle_id = handle->id;
497
498 post_processed_output_ = post_processed_output;
499 readback_buffer_queued_ = true;
500 readback_configured_ = false;
501 validated_ = false;
502
503 return HWC2::Error::None;
504 }
505
GetReadbackBufferFence(int32_t * release_fence)506 HWC2::Error HWCDisplayBuiltIn::GetReadbackBufferFence(int32_t *release_fence) {
507 auto status = HWC2::Error::None;
508
509 if (readback_configured_ && (output_buffer_.release_fence_fd >= 0)) {
510 *release_fence = output_buffer_.release_fence_fd;
511 } else {
512 status = HWC2::Error::Unsupported;
513 *release_fence = -1;
514 }
515
516 post_processed_output_ = false;
517 readback_buffer_queued_ = false;
518 readback_configured_ = false;
519 output_buffer_ = {};
520
521 return status;
522 }
523
TeardownConcurrentWriteback(void)524 DisplayError HWCDisplayBuiltIn::TeardownConcurrentWriteback(void) {
525 DisplayError error = kErrorNotSupported;
526
527 if (output_buffer_.release_fence_fd >= 0) {
528 int32_t release_fence_fd = dup(output_buffer_.release_fence_fd);
529 int ret = sync_wait(output_buffer_.release_fence_fd, 1000);
530 if (ret < 0) {
531 DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
532 }
533
534 ::close(release_fence_fd);
535 if (ret)
536 return kErrorResources;
537 }
538
539 if (display_intf_) {
540 error = display_intf_->TeardownConcurrentWriteback();
541 }
542
543 return error;
544 }
545
SetDisplayDppsAdROI(uint32_t h_start,uint32_t h_end,uint32_t v_start,uint32_t v_end,uint32_t factor_in,uint32_t factor_out)546 HWC2::Error HWCDisplayBuiltIn::SetDisplayDppsAdROI(uint32_t h_start, uint32_t h_end,
547 uint32_t v_start, uint32_t v_end,
548 uint32_t factor_in, uint32_t factor_out) {
549 DisplayError error = kErrorNone;
550 DisplayDppsAd4RoiCfg dpps_ad4_roi_cfg = {};
551 uint32_t panel_width = 0, panel_height = 0;
552 constexpr uint16_t kMaxFactorVal = 0xffff;
553
554 if (h_start >= h_end || v_start >= v_end || factor_in > kMaxFactorVal ||
555 factor_out > kMaxFactorVal) {
556 DLOGE("Invalid roi region = [%u, %u, %u, %u, %u, %u]",
557 h_start, h_end, v_start, v_end, factor_in, factor_out);
558 return HWC2::Error::BadParameter;
559 }
560
561 GetPanelResolution(&panel_width, &panel_height);
562
563 if (h_start >= panel_width || h_end > panel_width ||
564 v_start >= panel_height || v_end > panel_height) {
565 DLOGE("Invalid roi region = [%u, %u, %u, %u], panel resolution = [%u, %u]",
566 h_start, h_end, v_start, v_end, panel_width, panel_height);
567 return HWC2::Error::BadParameter;
568 }
569
570 dpps_ad4_roi_cfg.h_start = h_start;
571 dpps_ad4_roi_cfg.h_end = h_end;
572 dpps_ad4_roi_cfg.v_start = v_start;
573 dpps_ad4_roi_cfg.v_end = v_end;
574 dpps_ad4_roi_cfg.factor_in = factor_in;
575 dpps_ad4_roi_cfg.factor_out = factor_out;
576
577 error = display_intf_->SetDisplayDppsAdROI(&dpps_ad4_roi_cfg);
578 if (error)
579 return HWC2::Error::BadConfig;
580
581 callbacks_->Refresh(id_);
582
583 return HWC2::Error::None;
584 }
585
Perform(uint32_t operation,...)586 int HWCDisplayBuiltIn::Perform(uint32_t operation, ...) {
587 va_list args;
588 va_start(args, operation);
589 int val = 0;
590 LayerSolidFill *solid_fill_color;
591 LayerRect *rect = NULL;
592
593 switch (operation) {
594 case SET_METADATA_DYN_REFRESH_RATE:
595 val = va_arg(args, int32_t);
596 SetMetaDataRefreshRateFlag(val);
597 break;
598 case SET_BINDER_DYN_REFRESH_RATE:
599 val = va_arg(args, int32_t);
600 ForceRefreshRate(UINT32(val));
601 break;
602 case SET_DISPLAY_MODE:
603 val = va_arg(args, int32_t);
604 SetDisplayMode(UINT32(val));
605 break;
606 case SET_QDCM_SOLID_FILL_INFO:
607 solid_fill_color = va_arg(args, LayerSolidFill*);
608 SetQDCMSolidFillInfo(true, *solid_fill_color);
609 break;
610 case UNSET_QDCM_SOLID_FILL_INFO:
611 solid_fill_color = va_arg(args, LayerSolidFill*);
612 SetQDCMSolidFillInfo(false, *solid_fill_color);
613 break;
614 case SET_QDCM_SOLID_FILL_RECT:
615 rect = va_arg(args, LayerRect*);
616 solid_fill_rect_ = *rect;
617 break;
618 default:
619 DLOGW("Invalid operation %d", operation);
620 va_end(args);
621 return -EINVAL;
622 }
623 va_end(args);
624 validated_ = false;
625
626 return 0;
627 }
628
SetDisplayMode(uint32_t mode)629 DisplayError HWCDisplayBuiltIn::SetDisplayMode(uint32_t mode) {
630 DisplayError error = kErrorNone;
631
632 if (display_intf_) {
633 error = display_intf_->SetDisplayMode(mode);
634 if (error == kErrorNone) {
635 DisplayConfigFixedInfo fixed_info = {};
636 display_intf_->GetConfig(&fixed_info);
637 is_cmd_mode_ = fixed_info.is_cmdmode;
638 partial_update_enabled_ = fixed_info.partial_update;
639 for (auto hwc_layer : layer_set_) {
640 hwc_layer->SetPartialUpdate(partial_update_enabled_);
641 }
642 client_target_->SetPartialUpdate(partial_update_enabled_);
643 }
644 }
645
646 return error;
647 }
648
SetMetaDataRefreshRateFlag(bool enable)649 void HWCDisplayBuiltIn::SetMetaDataRefreshRateFlag(bool enable) {
650 int disable_metadata_dynfps = 0;
651
652 HWCDebugHandler::Get()->GetProperty(DISABLE_METADATA_DYNAMIC_FPS_PROP, &disable_metadata_dynfps);
653 if (disable_metadata_dynfps) {
654 return;
655 }
656 use_metadata_refresh_rate_ = enable;
657 }
658
SetQDCMSolidFillInfo(bool enable,const LayerSolidFill & color)659 void HWCDisplayBuiltIn::SetQDCMSolidFillInfo(bool enable, const LayerSolidFill &color) {
660 solid_fill_enable_ = enable;
661 solid_fill_color_ = color;
662 }
663
ToggleCPUHint(bool set)664 void HWCDisplayBuiltIn::ToggleCPUHint(bool set) {
665 if (!cpu_hint_) {
666 return;
667 }
668
669 if (set) {
670 cpu_hint_->Set();
671 } else {
672 cpu_hint_->Reset();
673 }
674 }
675
HandleSecureSession(const std::bitset<kSecureMax> & secure_sessions,bool * power_on_pending)676 int HWCDisplayBuiltIn::HandleSecureSession(const std::bitset<kSecureMax> &secure_sessions,
677 bool *power_on_pending) {
678 if (!power_on_pending) {
679 return -EINVAL;
680 }
681
682 if (current_power_mode_ != HWC2::PowerMode::On) {
683 return 0;
684 }
685
686 if (active_secure_sessions_[kSecureDisplay] != secure_sessions[kSecureDisplay]) {
687 SecureEvent secure_event =
688 secure_sessions.test(kSecureDisplay) ? kSecureDisplayStart : kSecureDisplayEnd;
689 DisplayError err = display_intf_->HandleSecureEvent(secure_event, &layer_stack_);
690 if (err != kErrorNone) {
691 DLOGE("Set secure event failed");
692 return err;
693 }
694 if (secure_event == kSecureDisplayStart) {
695 pmic_intf_->Notify(kSecureDisplayStart);
696 } else {
697 pmic_notification_pending_ = true;
698 }
699
700 DLOGI("SecureDisplay state changed from %d to %d for display %d",
701 active_secure_sessions_.test(kSecureDisplay), secure_sessions.test(kSecureDisplay),
702 type_);
703 }
704 active_secure_sessions_ = secure_sessions;
705 *power_on_pending = false;
706 return 0;
707 }
708
ForceRefreshRate(uint32_t refresh_rate)709 void HWCDisplayBuiltIn::ForceRefreshRate(uint32_t refresh_rate) {
710 if ((refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) ||
711 force_refresh_rate_ == refresh_rate) {
712 // Cannot honor force refresh rate, as its beyond the range or new request is same
713 return;
714 }
715
716 force_refresh_rate_ = refresh_rate;
717
718 callbacks_->Refresh(id_);
719
720 return;
721 }
722
GetOptimalRefreshRate(bool one_updating_layer)723 uint32_t HWCDisplayBuiltIn::GetOptimalRefreshRate(bool one_updating_layer) {
724 if (force_refresh_rate_) {
725 return force_refresh_rate_;
726 } else if (use_metadata_refresh_rate_ && one_updating_layer && metadata_refresh_rate_) {
727 return metadata_refresh_rate_;
728 }
729
730 return max_refresh_rate_;
731 }
732
Refresh()733 DisplayError HWCDisplayBuiltIn::Refresh() {
734 DisplayError error = kErrorNone;
735
736 callbacks_->Refresh(id_);
737
738 return error;
739 }
740
SetIdleTimeoutMs(uint32_t timeout_ms)741 void HWCDisplayBuiltIn::SetIdleTimeoutMs(uint32_t timeout_ms) {
742 display_intf_->SetIdleTimeoutMs(timeout_ms);
743 validated_ = false;
744 }
745
HandleFrameOutput()746 void HWCDisplayBuiltIn::HandleFrameOutput() {
747 if (readback_buffer_queued_) {
748 validated_ = false;
749 }
750
751 if (frame_capture_buffer_queued_) {
752 HandleFrameCapture();
753 } else if (dump_output_to_file_) {
754 HandleFrameDump();
755 }
756 }
757
HandleFrameCapture()758 void HWCDisplayBuiltIn::HandleFrameCapture() {
759 if (readback_configured_ && (output_buffer_.release_fence_fd >= 0)) {
760 frame_capture_status_ = sync_wait(output_buffer_.release_fence_fd, 1000);
761 ::close(output_buffer_.release_fence_fd);
762 output_buffer_.release_fence_fd = -1;
763 }
764
765 frame_capture_buffer_queued_ = false;
766 readback_buffer_queued_ = false;
767 post_processed_output_ = false;
768 readback_configured_ = false;
769 output_buffer_ = {};
770 }
771
HandleFrameDump()772 void HWCDisplayBuiltIn::HandleFrameDump() {
773 if (!readback_configured_) {
774 dump_frame_count_ = 0;
775 }
776
777 if (dump_frame_count_ && output_buffer_.release_fence_fd >= 0) {
778 int ret = sync_wait(output_buffer_.release_fence_fd, 1000);
779 ::close(output_buffer_.release_fence_fd);
780 output_buffer_.release_fence_fd = -1;
781 if (ret < 0) {
782 DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
783 } else {
784 DumpOutputBuffer(output_buffer_info_, output_buffer_base_, layer_stack_.retire_fence_fd);
785 readback_buffer_queued_ = false;
786 validated_ = false;
787 }
788 }
789
790 if (0 == dump_frame_count_) {
791 dump_output_to_file_ = false;
792 // Unmap and Free buffer
793 if (munmap(output_buffer_base_, output_buffer_info_.alloc_buffer_info.size) != 0) {
794 DLOGE("unmap failed with err %d", errno);
795 }
796 if (buffer_allocator_->FreeBuffer(&output_buffer_info_) != 0) {
797 DLOGE("FreeBuffer failed");
798 }
799
800 readback_buffer_queued_ = false;
801 post_processed_output_ = false;
802 readback_configured_ = false;
803
804 output_buffer_ = {};
805 output_buffer_info_ = {};
806 output_buffer_base_ = nullptr;
807 }
808 }
809
SetFrameDumpConfig(uint32_t count,uint32_t bit_mask_layer_type,int32_t format,bool post_processed)810 HWC2::Error HWCDisplayBuiltIn::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type,
811 int32_t format, bool post_processed) {
812 HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type, format, post_processed);
813 dump_output_to_file_ = bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP);
814 DLOGI("output_layer_dump_enable %d", dump_output_to_file_);
815
816 if (!count || !dump_output_to_file_ || (output_buffer_info_.alloc_buffer_info.fd >= 0)) {
817 return HWC2::Error::None;
818 }
819
820 // Allocate and map output buffer
821 if (post_processed) {
822 // To dump post-processed (DSPP) output, use Panel resolution.
823 GetPanelResolution(&output_buffer_info_.buffer_config.width,
824 &output_buffer_info_.buffer_config.height);
825 } else {
826 // To dump Layer Mixer output, use FrameBuffer resolution.
827 GetFrameBufferResolution(&output_buffer_info_.buffer_config.width,
828 &output_buffer_info_.buffer_config.height);
829 }
830
831 output_buffer_info_.buffer_config.format = HWCLayer::GetSDMFormat(format, 0);
832 output_buffer_info_.buffer_config.buffer_count = 1;
833 if (buffer_allocator_->AllocateBuffer(&output_buffer_info_) != 0) {
834 DLOGE("Buffer allocation failed");
835 output_buffer_info_ = {};
836 return HWC2::Error::NoResources;
837 }
838
839 void *buffer = mmap(NULL, output_buffer_info_.alloc_buffer_info.size, PROT_READ | PROT_WRITE,
840 MAP_SHARED, output_buffer_info_.alloc_buffer_info.fd, 0);
841
842 if (buffer == MAP_FAILED) {
843 DLOGE("mmap failed with err %d", errno);
844 buffer_allocator_->FreeBuffer(&output_buffer_info_);
845 output_buffer_info_ = {};
846 return HWC2::Error::NoResources;
847 }
848
849 output_buffer_base_ = buffer;
850 const native_handle_t *handle = static_cast<native_handle_t *>(output_buffer_info_.private_data);
851 SetReadbackBuffer(handle, -1, post_processed);
852
853 return HWC2::Error::None;
854 }
855
FrameCaptureAsync(const BufferInfo & output_buffer_info,bool post_processed_output)856 int HWCDisplayBuiltIn::FrameCaptureAsync(const BufferInfo &output_buffer_info,
857 bool post_processed_output) {
858 // Note: This function is called in context of a binder thread and a lock is already held
859 if (output_buffer_info.alloc_buffer_info.fd < 0) {
860 DLOGE("Invalid fd %d", output_buffer_info.alloc_buffer_info.fd);
861 return -1;
862 }
863
864 auto panel_width = 0u;
865 auto panel_height = 0u;
866 auto fb_width = 0u;
867 auto fb_height = 0u;
868
869 GetPanelResolution(&panel_width, &panel_height);
870 GetFrameBufferResolution(&fb_width, &fb_height);
871
872 if (post_processed_output && (output_buffer_info.buffer_config.width < panel_width ||
873 output_buffer_info.buffer_config.height < panel_height)) {
874 DLOGE("Buffer dimensions should not be less than panel resolution");
875 return -1;
876 } else if (!post_processed_output && (output_buffer_info.buffer_config.width < fb_width ||
877 output_buffer_info.buffer_config.height < fb_height)) {
878 DLOGE("Buffer dimensions should not be less than FB resolution");
879 return -1;
880 }
881
882 const native_handle_t *buffer = static_cast<native_handle_t *>(output_buffer_info.private_data);
883 SetReadbackBuffer(buffer, -1, post_processed_output);
884 frame_capture_buffer_queued_ = true;
885 frame_capture_status_ = -EAGAIN;
886
887 return 0;
888 }
889
SetDetailEnhancerConfig(const DisplayDetailEnhancerData & de_data)890 DisplayError HWCDisplayBuiltIn::SetDetailEnhancerConfig
891 (const DisplayDetailEnhancerData &de_data) {
892 DisplayError error = kErrorNotSupported;
893
894 if (display_intf_) {
895 error = display_intf_->SetDetailEnhancerData(de_data);
896 validated_ = false;
897 }
898 return error;
899 }
900
ControlPartialUpdate(bool enable,uint32_t * pending)901 DisplayError HWCDisplayBuiltIn::ControlPartialUpdate(bool enable, uint32_t *pending) {
902 DisplayError error = kErrorNone;
903
904 if (display_intf_) {
905 error = display_intf_->ControlPartialUpdate(enable, pending);
906 validated_ = false;
907 }
908
909 return error;
910 }
911
DisablePartialUpdateOneFrame()912 DisplayError HWCDisplayBuiltIn::DisablePartialUpdateOneFrame() {
913 DisplayError error = kErrorNone;
914
915 if (display_intf_) {
916 error = display_intf_->DisablePartialUpdateOneFrame();
917 validated_ = false;
918 }
919
920 return error;
921 }
922
SetDisplayedContentSamplingEnabledVndService(bool enabled)923 HWC2::Error HWCDisplayBuiltIn::SetDisplayedContentSamplingEnabledVndService(bool enabled) {
924 std::unique_lock<decltype(sampling_mutex)> lk(sampling_mutex);
925 vndservice_sampling_vote = enabled;
926 if (api_sampling_vote || vndservice_sampling_vote) {
927 histogram.start();
928 display_intf_->colorSamplingOn();
929 } else {
930 display_intf_->colorSamplingOff();
931 histogram.stop();
932 }
933 return HWC2::Error::None;
934 }
935
SetDisplayedContentSamplingEnabled(int32_t enabled,uint8_t component_mask,uint64_t max_frames)936 HWC2::Error HWCDisplayBuiltIn::SetDisplayedContentSamplingEnabled(int32_t enabled, uint8_t component_mask, uint64_t max_frames) {
937 if ((enabled != HWC2_DISPLAYED_CONTENT_SAMPLING_ENABLE) &&
938 (enabled != HWC2_DISPLAYED_CONTENT_SAMPLING_DISABLE))
939 return HWC2::Error::BadParameter;
940
941 std::unique_lock<decltype(sampling_mutex)> lk(sampling_mutex);
942 if (enabled == HWC2_DISPLAYED_CONTENT_SAMPLING_ENABLE) {
943 api_sampling_vote = true;
944 } else {
945 api_sampling_vote = false;
946 }
947
948 auto start = api_sampling_vote || vndservice_sampling_vote;
949 if (start && max_frames == 0) {
950 histogram.start();
951 display_intf_->colorSamplingOn();
952 } else if (start) {
953 histogram.start(max_frames);
954 display_intf_->colorSamplingOn();
955 } else {
956 display_intf_->colorSamplingOff();
957 histogram.stop();
958 }
959 return HWC2::Error::None;
960 }
961
GetDisplayedContentSamplingAttributes(int32_t * format,int32_t * dataspace,uint8_t * supported_components)962 HWC2::Error HWCDisplayBuiltIn::GetDisplayedContentSamplingAttributes(int32_t* format,
963 int32_t* dataspace,
964 uint8_t* supported_components) {
965 return histogram.getAttributes(format, dataspace, supported_components);
966 }
967
GetDisplayedContentSample(uint64_t max_frames,uint64_t timestamp,uint64_t * numFrames,int32_t samples_size[NUM_HISTOGRAM_COLOR_COMPONENTS],uint64_t * samples[NUM_HISTOGRAM_COLOR_COMPONENTS])968 HWC2::Error HWCDisplayBuiltIn::GetDisplayedContentSample(uint64_t max_frames,
969 uint64_t timestamp,
970 uint64_t* numFrames,
971 int32_t samples_size[NUM_HISTOGRAM_COLOR_COMPONENTS],
972 uint64_t* samples[NUM_HISTOGRAM_COLOR_COMPONENTS])
973 {
974 histogram.collect(max_frames, timestamp, samples_size, samples, numFrames);
975 return HWC2::Error::None;
976 }
977
GetDisplayBrightnessSupport(bool * out_support)978 HWC2::Error HWCDisplayBuiltIn::GetDisplayBrightnessSupport(bool *out_support) {
979 if (display_intf_->IsSupportPanelBrightnessControl()) {
980 *out_support = true;
981 } else {
982 *out_support = false;
983 }
984
985 return HWC2::Error::None;
986 }
987
GetProtectedContentsSupport(bool * out_support)988 HWC2::Error HWCDisplayBuiltIn::GetProtectedContentsSupport(bool *out_support) {
989 *out_support = true;
990 return HWC2::Error::None;
991 }
992
SetMixerResolution(uint32_t width,uint32_t height)993 DisplayError HWCDisplayBuiltIn::SetMixerResolution(uint32_t width, uint32_t height) {
994 DisplayError error = display_intf_->SetMixerResolution(width, height);
995 validated_ = false;
996 return error;
997 }
998
GetMixerResolution(uint32_t * width,uint32_t * height)999 DisplayError HWCDisplayBuiltIn::GetMixerResolution(uint32_t *width, uint32_t *height) {
1000 return display_intf_->GetMixerResolution(width, height);
1001 }
1002
SetQSyncMode(QSyncMode qsync_mode)1003 HWC2::Error HWCDisplayBuiltIn::SetQSyncMode(QSyncMode qsync_mode) {
1004 // Client needs to ensure that config change and qsync mode change
1005 // are not triggered in the same drawcycle.
1006 if (pending_config_) {
1007 DLOGE("Failed to set qsync mode. Pending active config transition");
1008 return HWC2::Error::Unsupported;
1009 }
1010
1011 auto err = display_intf_->SetQSyncMode(qsync_mode);
1012 if (err != kErrorNone) {
1013 return HWC2::Error::Unsupported;
1014 }
1015
1016 validated_ = false;
1017 return HWC2::Error::None;
1018 }
1019
ControlIdlePowerCollapse(bool enable,bool synchronous)1020 DisplayError HWCDisplayBuiltIn::ControlIdlePowerCollapse(bool enable, bool synchronous) {
1021 DisplayError error = kErrorNone;
1022
1023 if (display_intf_) {
1024 error = display_intf_->ControlIdlePowerCollapse(enable, synchronous);
1025 validated_ = false;
1026 }
1027 return error;
1028 }
1029
SetDynamicDSIClock(uint64_t bitclk)1030 DisplayError HWCDisplayBuiltIn::SetDynamicDSIClock(uint64_t bitclk) {
1031 DisplayError error = display_intf_->SetDynamicDSIClock(bitclk);
1032 if (error != kErrorNone) {
1033 DLOGE(" failed: Clk: %llu Error: %d", bitclk, error);
1034 return error;
1035 }
1036
1037 callbacks_->Refresh(id_);
1038 validated_ = false;
1039
1040 return kErrorNone;
1041 }
1042
GetDynamicDSIClock(uint64_t * bitclk)1043 DisplayError HWCDisplayBuiltIn::GetDynamicDSIClock(uint64_t *bitclk) {
1044 if (display_intf_) {
1045 return display_intf_->GetDynamicDSIClock(bitclk);
1046 }
1047
1048 return kErrorNotSupported;
1049 }
1050
GetSupportedDSIClock(std::vector<uint64_t> * bitclk_rates)1051 DisplayError HWCDisplayBuiltIn::GetSupportedDSIClock(std::vector<uint64_t> *bitclk_rates) {
1052 if (display_intf_) {
1053 return display_intf_->GetSupportedDSIClock(bitclk_rates);
1054 }
1055
1056 return kErrorNotSupported;
1057 }
1058
HistogramEvent(int fd,uint32_t blob_id)1059 DisplayError HWCDisplayBuiltIn::HistogramEvent(int fd, uint32_t blob_id) {
1060 histogram.notify_histogram_event(fd, blob_id);
1061 return kErrorNone;
1062 }
1063
UpdateDisplayId(hwc2_display_t id)1064 HWC2::Error HWCDisplayBuiltIn::UpdateDisplayId(hwc2_display_t id) {
1065 id_ = id;
1066 return HWC2::Error::None;
1067 }
1068
SetPendingRefresh()1069 HWC2::Error HWCDisplayBuiltIn::SetPendingRefresh() {
1070 pending_refresh_ = true;
1071 return HWC2::Error::None;
1072 }
1073
SetPanelBrightness(int32_t level)1074 HWC2::Error HWCDisplayBuiltIn::SetPanelBrightness(int32_t level) {
1075 DisplayError ret = display_intf_->SetPanelBrightness(level);
1076 if (ret != kErrorNone) {
1077 return HWC2::Error::NoResources;
1078 }
1079
1080 return HWC2::Error::None;
1081 }
1082
GetPanelBrightness(int32_t & level) const1083 HWC2::Error HWCDisplayBuiltIn::GetPanelBrightness(int32_t &level) const {
1084 DisplayError ret = display_intf_->GetPanelBrightness(level);
1085 if (ret != kErrorNone) {
1086 return HWC2::Error::NoResources;
1087 }
1088
1089 return HWC2::Error::None;
1090 }
1091
GetPanelMaxBrightness(int32_t & max_brightness_level) const1092 HWC2::Error HWCDisplayBuiltIn::GetPanelMaxBrightness(int32_t &max_brightness_level) const {
1093 DisplayError ret = display_intf_->GetPanelMaxBrightness(max_brightness_level);
1094 if (ret != kErrorNone) {
1095 return HWC2::Error::NoResources;
1096 }
1097 return HWC2::Error::None;
1098 }
1099
UpdatePowerMode(HWC2::PowerMode mode)1100 HWC2::Error HWCDisplayBuiltIn::UpdatePowerMode(HWC2::PowerMode mode) {
1101 current_power_mode_ = mode;
1102 validated_ = false;
1103 return HWC2::Error::None;
1104 }
1105
PostCommitLayerStack(int32_t * out_retire_fence)1106 HWC2::Error HWCDisplayBuiltIn::PostCommitLayerStack(int32_t *out_retire_fence) {
1107 if (pmic_notification_pending_) {
1108 // Wait for current commit to complete
1109 if (*out_retire_fence >= 0) {
1110 int ret = sync_wait(*out_retire_fence, 1000);
1111 if (ret < 0) {
1112 DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
1113 }
1114 }
1115 pmic_intf_->Notify(kSecureDisplayEnd);
1116 pmic_notification_pending_ = false;
1117 }
1118 return HWCDisplay::PostCommitLayerStack(out_retire_fence);
1119 }
1120
1121 } // namespace sdm
1122