1 /*
2 * Copyright (c) 2014 - 2018, 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_primary.h"
43 #include "hwc_debugger.h"
44
45 #define __CLASS__ "HWCDisplayPrimary"
46
47 namespace sdm {
48
Init()49 DisplayError HWCDisplayPrimary::PMICInterface::Init() {
50 std::string str_lcd_bias("/sys/class/lcd_bias/secure_mode");
51 fd_lcd_bias_ = ::open(str_lcd_bias.c_str(), O_WRONLY);
52 if (fd_lcd_bias_ < 0) {
53 DLOGE("File '%s' could not be opened. errno = %d, desc = %s", str_lcd_bias.c_str(), errno,
54 strerror(errno));
55 return kErrorHardware;
56 }
57
58 std::string str_leds_wled("/sys/class/leds/wled/secure_mode");
59 fd_wled_ = ::open(str_leds_wled.c_str(), O_WRONLY);
60 if (fd_wled_ < 0) {
61 DLOGE("File '%s' could not be opened. errno = %d, desc = %s", str_leds_wled.c_str(), errno,
62 strerror(errno));
63 return kErrorHardware;
64 }
65
66 return kErrorNone;
67 }
68
Deinit()69 void HWCDisplayPrimary::PMICInterface::Deinit() {
70 ::close(fd_lcd_bias_);
71 ::close(fd_wled_);
72 }
73
Notify(bool secure_display_start)74 DisplayError HWCDisplayPrimary::PMICInterface::Notify(bool secure_display_start) {
75 std::string str_sd_start = secure_display_start ? std::to_string(1) : std::to_string(0);
76 ssize_t err = ::pwrite(fd_lcd_bias_, str_sd_start.c_str(), str_sd_start.length(), 0);
77 if (err <= 0) {
78 DLOGE("Write failed for lcd_bias, Error = %s", strerror(errno));
79 return kErrorHardware;
80 }
81
82 err = ::pwrite(fd_wled_, str_sd_start.c_str(), str_sd_start.length(), 0);
83 if (err <= 0) {
84 DLOGE("Write failed for wled, Error = %s", strerror(errno));
85 return kErrorHardware;
86 }
87
88 DLOGI("Successfully notifed about secure display %s to PMIC driver",
89 secure_display_start ? "start": "end");
90 return kErrorNone;
91 }
92
Create(CoreInterface * core_intf,BufferAllocator * buffer_allocator,HWCCallbacks * callbacks,qService::QService * qservice,HWCDisplay ** hwc_display)93 int HWCDisplayPrimary::Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
94 HWCCallbacks *callbacks, qService::QService *qservice,
95 HWCDisplay **hwc_display) {
96 int status = 0;
97 uint32_t primary_width = 0;
98 uint32_t primary_height = 0;
99
100 HWCDisplay *hwc_display_primary =
101 new HWCDisplayPrimary(core_intf, buffer_allocator, callbacks, qservice);
102 status = hwc_display_primary->Init();
103 if (status) {
104 delete hwc_display_primary;
105 return status;
106 }
107
108 hwc_display_primary->GetMixerResolution(&primary_width, &primary_height);
109 int width = 0, height = 0;
110 HWCDebugHandler::Get()->GetProperty(FB_WIDTH_PROP, &width);
111 HWCDebugHandler::Get()->GetProperty(FB_HEIGHT_PROP, &height);
112 if (width > 0 && height > 0) {
113 primary_width = UINT32(width);
114 primary_height = UINT32(height);
115 }
116
117 status = hwc_display_primary->SetFrameBufferResolution(primary_width, primary_height);
118 if (status) {
119 Destroy(hwc_display_primary);
120 return status;
121 }
122
123 *hwc_display = hwc_display_primary;
124
125 return status;
126 }
127
Destroy(HWCDisplay * hwc_display)128 void HWCDisplayPrimary::Destroy(HWCDisplay *hwc_display) {
129 hwc_display->Deinit();
130 delete hwc_display;
131 }
132
HWCDisplayPrimary(CoreInterface * core_intf,BufferAllocator * buffer_allocator,HWCCallbacks * callbacks,qService::QService * qservice)133 HWCDisplayPrimary::HWCDisplayPrimary(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
134 HWCCallbacks *callbacks, qService::QService *qservice)
135 : HWCDisplay(core_intf, callbacks, kPrimary, HWC_DISPLAY_PRIMARY, true, qservice,
136 DISPLAY_CLASS_PRIMARY, buffer_allocator),
137 buffer_allocator_(buffer_allocator),
138 cpu_hint_(NULL) {
139 }
140
Init()141 int HWCDisplayPrimary::Init() {
142 cpu_hint_ = new CPUHint();
143 if (cpu_hint_->Init(static_cast<HWCDebugHandler *>(HWCDebugHandler::Get())) != kErrorNone) {
144 delete cpu_hint_;
145 cpu_hint_ = NULL;
146 }
147
148 use_metadata_refresh_rate_ = true;
149 int disable_metadata_dynfps = 0;
150 HWCDebugHandler::Get()->GetProperty(DISABLE_METADATA_DYNAMIC_FPS_PROP, &disable_metadata_dynfps);
151 if (disable_metadata_dynfps) {
152 use_metadata_refresh_rate_ = false;
153 }
154
155 int status = HWCDisplay::Init();
156 if (status) {
157 return status;
158 }
159 color_mode_ = new HWCColorMode(display_intf_);
160 color_mode_->Init();
161 HWCDebugHandler::Get()->GetProperty(ENABLE_DEFAULT_COLOR_MODE, &default_mode_status_);
162
163 pmic_intf_ = new PMICInterface();
164 pmic_intf_->Init();
165
166 return status;
167 }
168
Deinit()169 int HWCDisplayPrimary::Deinit() {
170 histogram.stop();
171
172 int status = HWCDisplay::Deinit();
173 if (status) {
174 return status;
175 }
176 pmic_intf_->Deinit();
177 delete pmic_intf_;
178
179 return 0;
180 }
181
Dump()182 std::string HWCDisplayPrimary::Dump() {
183 return HWCDisplay::Dump() + histogram.Dump();
184 }
185
ProcessBootAnimCompleted()186 void HWCDisplayPrimary::ProcessBootAnimCompleted() {
187 uint32_t numBootUpLayers = 0;
188 // TODO(user): Remove this hack
189
190 numBootUpLayers = static_cast<uint32_t>(Debug::GetBootAnimLayerCount());
191
192 if (numBootUpLayers == 0) {
193 numBootUpLayers = 2;
194 }
195 /* All other checks namely "init.svc.bootanim" or
196 * HWC_GEOMETRY_CHANGED fail in correctly identifying the
197 * exact bootup transition to homescreen
198 */
199 char property[PROPERTY_VALUE_MAX];
200 bool isEncrypted = false;
201 bool main_class_services_started = false;
202 property_get("ro.crypto.state", property, "unencrypted");
203 if (!strcmp(property, "encrypted")) {
204 property_get("ro.crypto.type", property, "block");
205 if (!strcmp(property, "block")) {
206 isEncrypted = true;
207 property_get("vold.decrypt", property, "");
208 if (!strcmp(property, "trigger_restart_framework")) {
209 main_class_services_started = true;
210 }
211 }
212 }
213
214 if ((!isEncrypted || (isEncrypted && main_class_services_started)) &&
215 (layer_set_.size() > numBootUpLayers)) {
216 DLOGI("Applying default mode");
217 boot_animation_completed_ = true;
218 // Applying default mode after bootanimation is finished And
219 // If Data is Encrypted, it is ready for access.
220 if (display_intf_) {
221 display_intf_->ApplyDefaultDisplayMode();
222 RestoreColorTransform();
223 }
224 }
225 }
226
Validate(uint32_t * out_num_types,uint32_t * out_num_requests)227 HWC2::Error HWCDisplayPrimary::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
228 auto status = HWC2::Error::None;
229 DisplayError error = kErrorNone;
230
231 if (default_mode_status_ && !boot_animation_completed_) {
232 ProcessBootAnimCompleted();
233 }
234
235 if (display_paused_) {
236 MarkLayersForGPUBypass();
237 return status;
238 }
239
240 if (color_tranform_failed_) {
241 // Must fall back to client composition
242 MarkLayersForClientComposition();
243 }
244
245 if (config_pending_) {
246 if (display_intf_->SetActiveConfig(display_config_) != kErrorNone) {
247 DLOGW("Invalid display config %d", display_config_);
248 // Reset the display config with active config
249 display_intf_->GetActiveConfig(&display_config_);
250 }
251 }
252 // Fill in the remaining blanks in the layers and add them to the SDM layerstack
253 BuildLayerStack();
254 // Checks and replaces layer stack for solid fill
255 SolidFillPrepare();
256
257 bool pending_output_dump = dump_frame_count_ && dump_output_to_file_;
258
259 if (readback_buffer_queued_ || pending_output_dump) {
260 CloseFd(&output_buffer_.release_fence_fd);
261 // RHS values were set in FrameCaptureAsync() called from a binder thread. They are picked up
262 // here in a subsequent draw round. Readback is not allowed for any secure use case.
263 readback_configured_ = !layer_stack_.flags.secure_present;
264 if (readback_configured_) {
265 DisablePartialUpdateOneFrame();
266 layer_stack_.output_buffer = &output_buffer_;
267 layer_stack_.flags.post_processed_output = post_processed_output_;
268 }
269 }
270
271 uint32_t num_updating_layers = GetUpdatingLayersCount();
272 bool one_updating_layer = (num_updating_layers == 1);
273 if (num_updating_layers != 0) {
274 ToggleCPUHint(one_updating_layer);
275 }
276
277 uint32_t refresh_rate = GetOptimalRefreshRate(one_updating_layer);
278 bool final_rate = force_refresh_rate_ ? true : false;
279 error = display_intf_->SetRefreshRate(refresh_rate, final_rate);
280 if (error == kErrorNone) {
281 // On success, set current refresh rate to new refresh rate
282 current_refresh_rate_ = refresh_rate;
283 }
284
285 if (layer_set_.empty()) {
286 // Avoid flush for Command mode panel.
287 DisplayConfigFixedInfo display_config;
288 display_intf_->GetConfig(&display_config);
289 flush_ = !(display_config.is_cmdmode && secure_display_active_);
290 validated_ = true;
291 return status;
292 }
293
294 status = PrepareLayerStack(out_num_types, out_num_requests);
295 pending_commit_ = true;
296 return status;
297 }
298
Present(int32_t * out_retire_fence)299 HWC2::Error HWCDisplayPrimary::Present(int32_t *out_retire_fence) {
300 auto status = HWC2::Error::None;
301 if (display_paused_) {
302 // TODO(user): From old HWC implementation
303 // If we do not handle the frame set retireFenceFd to outbufAcquireFenceFd
304 // Revisit this when validating display_paused
305 DisplayError error = display_intf_->Flush();
306 validated_ = false;
307 if (error != kErrorNone) {
308 DLOGE("Flush failed. Error = %d", error);
309 }
310 } else {
311 status = HWCDisplay::CommitLayerStack();
312 if (status == HWC2::Error::None) {
313 HandleFrameOutput();
314 SolidFillCommit();
315 status = PostCommitLayerStack(out_retire_fence);
316 }
317 }
318
319 if (CC_UNLIKELY(!has_init_light_server_)) {
320 using ILight = ::hardware::google::light::V1_0::ILight;
321 vendor_ILight_ = ILight::getService();
322 if (vendor_ILight_ != nullptr) {
323 vendor_ILight_->setHbm(false);
324 } else {
325 DLOGE("failed to get vendor light service");
326 }
327
328 uint32_t panel_x, panel_y;
329 GetPanelResolution(&panel_x, &panel_y);
330 hbm_threshold_px_ = float(panel_x * panel_y) * hbm_threshold_pct_;
331 DLOGI("Configure hbm_threshold_px_ to %f", hbm_threshold_px_);
332
333 has_init_light_server_ = true;
334 }
335
336 const bool enable_hbm(hdr_largest_layer_px_ > hbm_threshold_px_);
337 if (high_brightness_mode_ != enable_hbm && vendor_ILight_ != nullptr) {
338 using ::android::hardware::light::V2_0::Status;
339 if (Status::SUCCESS == vendor_ILight_->setHbm(enable_hbm)) {
340 high_brightness_mode_ = enable_hbm;
341 } else {
342 DLOGE("failed to setHbm to %d", enable_hbm);
343 }
344 }
345
346 CloseFd(&output_buffer_.acquire_fence_fd);
347 pending_commit_ = false;
348 return status;
349 }
350
GetColorModes(uint32_t * out_num_modes,ColorMode * out_modes)351 HWC2::Error HWCDisplayPrimary::GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes) {
352 if (out_modes == nullptr) {
353 *out_num_modes = color_mode_->GetColorModeCount();
354 } else {
355 color_mode_->GetColorModes(out_num_modes, out_modes);
356 }
357
358 return HWC2::Error::None;
359 }
360
GetRenderIntents(ColorMode mode,uint32_t * out_num_intents,RenderIntent * out_intents)361 HWC2::Error HWCDisplayPrimary::GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
362 RenderIntent *out_intents) {
363 if (out_intents == nullptr) {
364 *out_num_intents = color_mode_->GetRenderIntentCount(mode);
365 } else {
366 color_mode_->GetRenderIntents(mode, out_num_intents, out_intents);
367 }
368 return HWC2::Error::None;
369 }
370
SetColorMode(ColorMode mode)371 HWC2::Error HWCDisplayPrimary::SetColorMode(ColorMode mode) {
372 return SetColorModeWithRenderIntent(mode, RenderIntent::COLORIMETRIC);
373 }
374
SetWhiteCompensation(bool enabled)375 HWC2::Error HWCDisplayPrimary::SetWhiteCompensation(bool enabled) {
376 auto status = color_mode_->SetWhiteCompensation(enabled);
377 if (status != HWC2::Error::None) {
378 DLOGE("failed for SetWhiteCompensation to %d", enabled);
379 return status;
380 }
381
382 callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
383
384 return status;
385 }
386
SetColorModeWithRenderIntent(ColorMode mode,RenderIntent intent)387 HWC2::Error HWCDisplayPrimary::SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
388 auto status = color_mode_->SetColorModeWithRenderIntent(mode, intent);
389 if (status != HWC2::Error::None) {
390 DLOGE("failed for mode = %d intent = %d", mode, intent);
391 return status;
392 }
393 callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
394 validated_ = false;
395 auto working_color_space = color_mode_->GetWorkingColorSpace();
396 working_primaries_ = working_color_space.first;
397 working_transfer_ = working_color_space.second;
398 current_color_mode_ = color_mode_->GetCurrentColorMode();
399 return status;
400 }
401
SetColorModeById(int32_t color_mode_id)402 HWC2::Error HWCDisplayPrimary::SetColorModeById(int32_t color_mode_id) {
403 auto status = color_mode_->SetColorModeById(color_mode_id);
404 if (status != HWC2::Error::None) {
405 DLOGE("failed for mode = %d", color_mode_id);
406 return status;
407 }
408
409 callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
410 validated_ = false;
411
412 return status;
413 }
414
RestoreColorTransform()415 HWC2::Error HWCDisplayPrimary::RestoreColorTransform() {
416 auto status = color_mode_->RestoreColorTransform();
417 if (status != HWC2::Error::None) {
418 DLOGE("failed to RestoreColorTransform");
419 return status;
420 }
421
422 callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
423
424 return status;
425 }
426
SetColorTransform(const float * matrix,android_color_transform_t hint)427 HWC2::Error HWCDisplayPrimary::SetColorTransform(const float *matrix,
428 android_color_transform_t hint) {
429 if (!matrix) {
430 return HWC2::Error::BadParameter;
431 }
432
433 auto status = color_mode_->SetColorTransform(matrix, hint);
434 if (status != HWC2::Error::None) {
435 DLOGE("failed for hint = %d", hint);
436 color_tranform_failed_ = true;
437 return status;
438 }
439
440 callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
441 color_tranform_failed_ = false;
442 validated_ = false;
443
444 return status;
445 }
446
SetReadbackBuffer(const native_handle_t * buffer,int32_t acquire_fence,bool post_processed_output)447 HWC2::Error HWCDisplayPrimary::SetReadbackBuffer(const native_handle_t *buffer,
448 int32_t acquire_fence,
449 bool post_processed_output) {
450 const private_handle_t *handle = reinterpret_cast<const private_handle_t *>(buffer);
451 if (!handle || (handle->fd < 0)) {
452 return HWC2::Error::BadParameter;
453 }
454
455 // Configure the output buffer as Readback buffer
456 output_buffer_.width = UINT32(handle->width);
457 output_buffer_.height = UINT32(handle->height);
458 output_buffer_.unaligned_width = UINT32(handle->unaligned_width);
459 output_buffer_.unaligned_height = UINT32(handle->unaligned_height);
460 output_buffer_.format = GetSDMFormat(handle->format, handle->flags);
461 output_buffer_.planes[0].fd = handle->fd;
462 output_buffer_.planes[0].stride = UINT32(handle->width);
463 output_buffer_.acquire_fence_fd = dup(acquire_fence);
464 output_buffer_.release_fence_fd = -1;
465
466 post_processed_output_ = post_processed_output;
467 readback_buffer_queued_ = true;
468 readback_configured_ = false;
469 validated_ = false;
470
471 return HWC2::Error::None;
472 }
473
GetReadbackBufferFence(int32_t * release_fence)474 HWC2::Error HWCDisplayPrimary::GetReadbackBufferFence(int32_t *release_fence) {
475 auto status = HWC2::Error::None;
476
477 if (readback_configured_ && (output_buffer_.release_fence_fd >= 0)) {
478 *release_fence = output_buffer_.release_fence_fd;
479 } else {
480 status = HWC2::Error::Unsupported;
481 *release_fence = -1;
482 }
483
484 post_processed_output_ = false;
485 readback_buffer_queued_ = false;
486 readback_configured_ = false;
487 output_buffer_ = {};
488
489 return status;
490 }
491
PostCommitLayerStack(int32_t * out_retire_fence)492 HWC2::Error HWCDisplayPrimary::PostCommitLayerStack(int32_t *out_retire_fence) {
493 auto status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
494 if (status != HWC2::Error::None) {
495 return status;
496 }
497
498 if (pmic_notification_pending_) {
499 // Wait for current commit to complete
500 if (*out_retire_fence >= 0) {
501 int ret = sync_wait(*out_retire_fence, 1000);
502 if (ret < 0) {
503 DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
504 }
505 }
506 pmic_intf_->Notify(false /* secure_display_start */);
507 pmic_notification_pending_ = false;
508 }
509 return HWC2::Error::None;
510 }
511
TeardownConcurrentWriteback(void)512 DisplayError HWCDisplayPrimary::TeardownConcurrentWriteback(void) {
513 DisplayError error = kErrorNotSupported;
514
515 if (output_buffer_.release_fence_fd >= 0) {
516 int32_t release_fence_fd = dup(output_buffer_.release_fence_fd);
517 int ret = sync_wait(output_buffer_.release_fence_fd, 1000);
518 if (ret < 0) {
519 DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
520 }
521
522 ::close(release_fence_fd);
523 if (ret)
524 return kErrorResources;
525 }
526
527 if (display_intf_) {
528 error = display_intf_->TeardownConcurrentWriteback();
529 }
530
531 return error;
532 }
533
Perform(uint32_t operation,...)534 int HWCDisplayPrimary::Perform(uint32_t operation, ...) {
535 va_list args;
536 va_start(args, operation);
537 int val = 0;
538 LayerSolidFill *solid_fill_color;
539 LayerRect *rect = NULL;
540
541 switch (operation) {
542 case SET_METADATA_DYN_REFRESH_RATE:
543 val = va_arg(args, int32_t);
544 SetMetaDataRefreshRateFlag(val);
545 break;
546 case SET_BINDER_DYN_REFRESH_RATE:
547 val = va_arg(args, int32_t);
548 ForceRefreshRate(UINT32(val));
549 break;
550 case SET_DISPLAY_MODE:
551 val = va_arg(args, int32_t);
552 SetDisplayMode(UINT32(val));
553 break;
554 case SET_QDCM_SOLID_FILL_INFO:
555 solid_fill_color = va_arg(args, LayerSolidFill*);
556 SetQDCMSolidFillInfo(true, *solid_fill_color);
557 break;
558 case UNSET_QDCM_SOLID_FILL_INFO:
559 solid_fill_color = va_arg(args, LayerSolidFill*);
560 SetQDCMSolidFillInfo(false, *solid_fill_color);
561 break;
562 case SET_QDCM_SOLID_FILL_RECT:
563 rect = va_arg(args, LayerRect*);
564 solid_fill_rect_ = *rect;
565 break;
566 default:
567 DLOGW("Invalid operation %d", operation);
568 va_end(args);
569 return -EINVAL;
570 }
571 va_end(args);
572 validated_ = false;
573
574 return 0;
575 }
576
SetDisplayMode(uint32_t mode)577 DisplayError HWCDisplayPrimary::SetDisplayMode(uint32_t mode) {
578 DisplayError error = kErrorNone;
579
580 if (display_intf_) {
581 error = display_intf_->SetDisplayMode(mode);
582 }
583
584 return error;
585 }
586
SetMetaDataRefreshRateFlag(bool enable)587 void HWCDisplayPrimary::SetMetaDataRefreshRateFlag(bool enable) {
588 int disable_metadata_dynfps = 0;
589
590 HWCDebugHandler::Get()->GetProperty(DISABLE_METADATA_DYNAMIC_FPS_PROP, &disable_metadata_dynfps);
591 if (disable_metadata_dynfps) {
592 return;
593 }
594 use_metadata_refresh_rate_ = enable;
595 }
596
SetQDCMSolidFillInfo(bool enable,const LayerSolidFill & color)597 void HWCDisplayPrimary::SetQDCMSolidFillInfo(bool enable, const LayerSolidFill &color) {
598 solid_fill_enable_ = enable;
599 solid_fill_color_ = color;
600 }
601
ToggleCPUHint(bool set)602 void HWCDisplayPrimary::ToggleCPUHint(bool set) {
603 if (!cpu_hint_) {
604 return;
605 }
606
607 if (set) {
608 cpu_hint_->Set();
609 } else {
610 cpu_hint_->Reset();
611 }
612 }
613
SetSecureDisplay(bool secure_display_active)614 void HWCDisplayPrimary::SetSecureDisplay(bool secure_display_active) {
615 if (secure_display_active_ != secure_display_active) {
616 // Skip Prepare and call Flush for null commit
617 DLOGI("SecureDisplay state changed from %d to %d Needs Flush!!", secure_display_active_,
618 secure_display_active);
619 secure_display_active_ = secure_display_active;
620 if (secure_display_active_) {
621 pmic_intf_->Notify(true /* secure_display_start */);
622 } else {
623 pmic_notification_pending_ = true;
624 }
625
626 // Avoid flush for Command mode panel.
627 DisplayConfigFixedInfo display_config;
628 display_intf_->GetConfig(&display_config);
629 skip_prepare_ = !display_config.is_cmdmode;
630 }
631 }
632
ForceRefreshRate(uint32_t refresh_rate)633 void HWCDisplayPrimary::ForceRefreshRate(uint32_t refresh_rate) {
634 if ((refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) ||
635 force_refresh_rate_ == refresh_rate) {
636 // Cannot honor force refresh rate, as its beyond the range or new request is same
637 return;
638 }
639
640 force_refresh_rate_ = refresh_rate;
641
642 callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
643
644 return;
645 }
646
GetOptimalRefreshRate(bool one_updating_layer)647 uint32_t HWCDisplayPrimary::GetOptimalRefreshRate(bool one_updating_layer) {
648 if (force_refresh_rate_) {
649 return force_refresh_rate_;
650 } else if (use_metadata_refresh_rate_ && one_updating_layer && metadata_refresh_rate_) {
651 return metadata_refresh_rate_;
652 }
653
654 return max_refresh_rate_;
655 }
656
Refresh()657 DisplayError HWCDisplayPrimary::Refresh() {
658 DisplayError error = kErrorNone;
659
660 callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
661
662 return error;
663 }
664
SetIdleTimeoutMs(uint32_t timeout_ms)665 void HWCDisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
666 display_intf_->SetIdleTimeoutMs(timeout_ms);
667 validated_ = false;
668 }
669
HandleFrameOutput()670 void HWCDisplayPrimary::HandleFrameOutput() {
671 if (readback_buffer_queued_) {
672 validated_ = false;
673 }
674
675 if (dump_output_to_file_) {
676 HandleFrameDump();
677 }
678 }
679
HandleFrameDump()680 void HWCDisplayPrimary::HandleFrameDump() {
681 if (!readback_configured_) {
682 dump_frame_count_ = 0;
683 }
684
685 if (dump_frame_count_ && output_buffer_.release_fence_fd >= 0) {
686 int ret = sync_wait(output_buffer_.release_fence_fd, 1000);
687 ::close(output_buffer_.release_fence_fd);
688 output_buffer_.release_fence_fd = -1;
689 if (ret < 0) {
690 DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
691 } else {
692 DumpOutputBuffer(output_buffer_info_, output_buffer_base_, layer_stack_.retire_fence_fd);
693 readback_buffer_queued_ = false;
694 validated_ = false;
695 }
696 }
697
698 if (0 == dump_frame_count_) {
699 dump_output_to_file_ = false;
700 // Unmap and Free buffer
701 if (munmap(output_buffer_base_, output_buffer_info_.alloc_buffer_info.size) != 0) {
702 DLOGE("unmap failed with err %d", errno);
703 }
704 if (buffer_allocator_->FreeBuffer(&output_buffer_info_) != 0) {
705 DLOGE("FreeBuffer failed");
706 }
707
708 readback_buffer_queued_ = false;
709 post_processed_output_ = false;
710 readback_configured_ = false;
711
712 output_buffer_ = {};
713 output_buffer_info_ = {};
714 output_buffer_base_ = nullptr;
715 }
716 }
717
SetFrameDumpConfig(uint32_t count,uint32_t bit_mask_layer_type,int32_t format,bool post_processed)718 HWC2::Error HWCDisplayPrimary::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type,
719 int32_t format, bool post_processed) {
720 HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type, format, post_processed);
721 dump_output_to_file_ = bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP);
722 DLOGI("output_layer_dump_enable %d", dump_output_to_file_);
723
724 if (!count || !dump_output_to_file_) {
725 return HWC2::Error::None;
726 }
727
728 // Allocate and map output buffer
729 output_buffer_info_ = {};
730
731 if (post_processed) {
732 // To dump post-processed (DSPP) output, use Panel resolution.
733 GetPanelResolution(&output_buffer_info_.buffer_config.width,
734 &output_buffer_info_.buffer_config.height);
735 } else {
736 // To dump Layer Mixer output, use FrameBuffer resolution.
737 GetFrameBufferResolution(&output_buffer_info_.buffer_config.width,
738 &output_buffer_info_.buffer_config.height);
739 }
740
741 output_buffer_info_.buffer_config.format = GetSDMFormat(format, 0);
742 output_buffer_info_.buffer_config.buffer_count = 1;
743 if (buffer_allocator_->AllocateBuffer(&output_buffer_info_) != 0) {
744 DLOGE("Buffer allocation failed");
745 output_buffer_info_ = {};
746 return HWC2::Error::NoResources;
747 }
748
749 void *buffer = mmap(NULL, output_buffer_info_.alloc_buffer_info.size, PROT_READ | PROT_WRITE,
750 MAP_SHARED, output_buffer_info_.alloc_buffer_info.fd, 0);
751
752 if (buffer == MAP_FAILED) {
753 DLOGE("mmap failed with err %d", errno);
754 buffer_allocator_->FreeBuffer(&output_buffer_info_);
755 output_buffer_info_ = {};
756 return HWC2::Error::NoResources;
757 }
758
759 output_buffer_base_ = buffer;
760 const native_handle_t *handle = static_cast<native_handle_t *>(output_buffer_info_.private_data);
761 SetReadbackBuffer(handle, -1, post_processed);
762
763 return HWC2::Error::None;
764 }
765
FrameCaptureAsync(const BufferInfo & output_buffer_info,bool post_processed_output)766 int HWCDisplayPrimary::FrameCaptureAsync(const BufferInfo &output_buffer_info,
767 bool post_processed_output) {
768 // Note: This function is called in context of a binder thread and a lock is already held
769 if (output_buffer_info.alloc_buffer_info.fd < 0) {
770 DLOGE("Invalid fd %d", output_buffer_info.alloc_buffer_info.fd);
771 return -1;
772 }
773
774 auto panel_width = 0u;
775 auto panel_height = 0u;
776 auto fb_width = 0u;
777 auto fb_height = 0u;
778
779 GetPanelResolution(&panel_width, &panel_height);
780 GetFrameBufferResolution(&fb_width, &fb_height);
781
782 if (post_processed_output && (output_buffer_info.buffer_config.width < panel_width ||
783 output_buffer_info.buffer_config.height < panel_height)) {
784 DLOGE("Buffer dimensions should not be less than panel resolution");
785 return -1;
786 } else if (!post_processed_output && (output_buffer_info.buffer_config.width < fb_width ||
787 output_buffer_info.buffer_config.height < fb_height)) {
788 DLOGE("Buffer dimensions should not be less than FB resolution");
789 return -1;
790 }
791
792 const native_handle_t *buffer = static_cast<native_handle_t *>(output_buffer_info.private_data);
793 SetReadbackBuffer(buffer, -1, post_processed_output);
794
795 return 0;
796 }
797
GetFrameCaptureFence(int32_t * release_fence)798 bool HWCDisplayPrimary::GetFrameCaptureFence(int32_t *release_fence) {
799 return (GetReadbackBufferFence(release_fence) == HWC2::Error::None);
800 }
801
SetDetailEnhancerConfig(const DisplayDetailEnhancerData & de_data)802 DisplayError HWCDisplayPrimary::SetDetailEnhancerConfig
803 (const DisplayDetailEnhancerData &de_data) {
804 DisplayError error = kErrorNotSupported;
805
806 if (display_intf_) {
807 error = display_intf_->SetDetailEnhancerData(de_data);
808 validated_ = false;
809 }
810 return error;
811 }
812
ControlPartialUpdate(bool enable,uint32_t * pending)813 DisplayError HWCDisplayPrimary::ControlPartialUpdate(bool enable, uint32_t *pending) {
814 DisplayError error = kErrorNone;
815
816 if (display_intf_) {
817 error = display_intf_->ControlPartialUpdate(enable, pending);
818 validated_ = false;
819 }
820
821 return error;
822 }
823
DisablePartialUpdateOneFrame()824 DisplayError HWCDisplayPrimary::DisablePartialUpdateOneFrame() {
825 DisplayError error = kErrorNone;
826
827 if (display_intf_) {
828 error = display_intf_->DisablePartialUpdateOneFrame();
829 validated_ = false;
830 }
831
832 return error;
833 }
834
SetDisplayedContentSamplingEnabledVndService(bool enabled)835 HWC2::Error HWCDisplayPrimary::SetDisplayedContentSamplingEnabledVndService(bool enabled) {
836 std::unique_lock<decltype(sampling_mutex)> lk(sampling_mutex);
837 vndservice_sampling_vote = enabled;
838 if (api_sampling_vote || vndservice_sampling_vote) {
839 histogram.start();
840 } else {
841 histogram.stop();
842 }
843 return HWC2::Error::None;
844 }
845
SetDisplayedContentSamplingEnabled(int32_t enabled,uint8_t component_mask,uint64_t max_frames)846 HWC2::Error HWCDisplayPrimary::SetDisplayedContentSamplingEnabled(int32_t enabled, uint8_t component_mask, uint64_t max_frames) {
847 if ((enabled != HWC2_DISPLAYED_CONTENT_SAMPLING_ENABLE) &&
848 (enabled != HWC2_DISPLAYED_CONTENT_SAMPLING_DISABLE))
849 return HWC2::Error::BadParameter;
850
851 std::unique_lock<decltype(sampling_mutex)> lk(sampling_mutex);
852 if (enabled == HWC2_DISPLAYED_CONTENT_SAMPLING_ENABLE) {
853 api_sampling_vote = true;
854 } else {
855 api_sampling_vote = false;
856 }
857
858 auto start = api_sampling_vote || vndservice_sampling_vote;
859 if (start && max_frames == 0) {
860 histogram.start();
861 } else if (start) {
862 histogram.start(max_frames);
863 } else {
864 histogram.stop();
865 }
866 return HWC2::Error::None;
867 }
868
GetDisplayedContentSamplingAttributes(int32_t * format,int32_t * dataspace,uint8_t * supported_components)869 HWC2::Error HWCDisplayPrimary::GetDisplayedContentSamplingAttributes(int32_t* format,
870 int32_t* dataspace,
871 uint8_t* supported_components) {
872 return histogram.getAttributes(format, dataspace, supported_components);
873 }
874
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])875 HWC2::Error HWCDisplayPrimary::GetDisplayedContentSample(uint64_t max_frames,
876 uint64_t timestamp,
877 uint64_t* numFrames,
878 int32_t samples_size[NUM_HISTOGRAM_COLOR_COMPONENTS],
879 uint64_t* samples[NUM_HISTOGRAM_COLOR_COMPONENTS])
880 {
881 histogram.collect(max_frames, timestamp, samples_size, samples, numFrames);
882 return HWC2::Error::None;
883 }
884
SetMixerResolution(uint32_t width,uint32_t height)885 DisplayError HWCDisplayPrimary::SetMixerResolution(uint32_t width, uint32_t height) {
886 DisplayError error = display_intf_->SetMixerResolution(width, height);
887 validated_ = false;
888 return error;
889 }
890
GetMixerResolution(uint32_t * width,uint32_t * height)891 DisplayError HWCDisplayPrimary::GetMixerResolution(uint32_t *width, uint32_t *height) {
892 return display_intf_->GetMixerResolution(width, height);
893 }
894
ControlIdlePowerCollapse(bool enable,bool synchronous)895 HWC2::Error HWCDisplayPrimary::ControlIdlePowerCollapse(bool enable, bool synchronous) {
896 DisplayError error = kErrorNone;
897
898 if (display_intf_) {
899 error = display_intf_->ControlIdlePowerCollapse(enable, synchronous);
900 validated_ = false;
901 }
902
903 return (error != kErrorNone) ? HWC2::Error::Unsupported : HWC2::Error::None;
904 }
905
906 } // namespace sdm
907