1 /*
2 * Copyright (c) 2014-2020, 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 <android-base/file.h>
31 #include <cutils/properties.h>
32 #include <cutils/sockets.h>
33 #include <utils/constants.h>
34 #include <utils/debug.h>
35 #include <utils/utils.h>
36 #include <stdarg.h>
37 #include <sync/sync.h>
38 #include <sys/mman.h>
39
40 #include <map>
41 #include <iostream>
42 #include <string>
43 #include <vector>
44
45 #include "hwc_display_builtin.h"
46 #include "hwc_debugger.h"
47 #include "hwc_session.h"
48
49 #define __CLASS__ "HWCDisplayBuiltIn"
50
51 namespace sdm {
52
SetRect(LayerRect & src_rect,GLRect * target)53 static void SetRect(LayerRect &src_rect, GLRect *target) {
54 target->left = src_rect.left;
55 target->top = src_rect.top;
56 target->right = src_rect.right;
57 target->bottom = src_rect.bottom;
58 }
59
LoadPanelGammaCalibration()60 static std::string LoadPanelGammaCalibration() {
61 constexpr char file[] = "/mnt/vendor/persist/display/gamma_calib_data.cal";
62 std::ifstream ifs(file);
63
64 if (!ifs.is_open()) {
65 DLOGW("Unable to open gamma calibration '%s', error = %s", file, strerror(errno));
66 return {};
67 }
68
69 std::string raw_data, gamma;
70 while (std::getline(ifs, raw_data, '\r')) {
71 gamma.append(raw_data.c_str());
72 gamma.append(" ");
73 std::getline(ifs, raw_data);
74 }
75 ifs.close();
76
77 /* eliminate space character in the last byte */
78 if (!gamma.empty()) {
79 gamma.pop_back();
80 }
81
82 return gamma;
83 }
84
WritePanelGammaTableToDriver(const std::string & gamma_data)85 static DisplayError WritePanelGammaTableToDriver(const std::string &gamma_data) {
86 constexpr char gamma_path[] = "/sys/devices/platform/soc/soc:qcom,dsi-display-primary/gamma";
87 int fd = open(gamma_path, O_WRONLY);
88 if (fd < 0) {
89 DLOGW("Unable to open gamma node '%s', error = %s", gamma_path, strerror(errno));
90 return kErrorFileDescriptor;
91 }
92
93 constexpr int max_retries = 5;
94 ssize_t len;
95 int retry_count = 0;
96 DisplayError error = kErrorNone;
97 while ((len = pwrite(fd, gamma_data.c_str(), gamma_data.size(), 0)) != gamma_data.size()) {
98 if ((len == -1 && errno != EINTR && errno != EAGAIN) || (++retry_count > max_retries)) {
99 DLOGE("Failed to write gamma calibration(retry %d), error = %s", retry_count,
100 strerror(errno));
101 break;
102 }
103 }
104 close(fd);
105
106 if (len != gamma_data.size()) {
107 error = kErrorResources;
108 }
109
110 return error;
111 }
112
UpdatePanelGammaTable(enum HWCDisplay::PanelGammaSource source)113 static DisplayError UpdatePanelGammaTable(enum HWCDisplay::PanelGammaSource source) {
114 std::string gamma_data = {};
115 DisplayError error;
116 if (source == HWCDisplay::kGammaDefault) {
117 gamma_data = "default";
118 } else if (source == HWCDisplay::kGammaCalibration) {
119 gamma_data = LoadPanelGammaCalibration();
120 }
121
122 if (!gamma_data.empty()) {
123 error = WritePanelGammaTableToDriver(gamma_data);
124 } else {
125 error = kErrorParameters;
126 }
127
128 return error;
129 }
130
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)131 int HWCDisplayBuiltIn::Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
132 HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
133 qService::QService *qservice, hwc2_display_t id, int32_t sdm_id,
134 HWCDisplay **hwc_display) {
135 int status = 0;
136 uint32_t builtin_width = 0;
137 uint32_t builtin_height = 0;
138
139 HWCDisplay *hwc_display_builtin =
140 new HWCDisplayBuiltIn(core_intf, buffer_allocator, callbacks, event_handler, qservice, id,
141 sdm_id);
142 status = hwc_display_builtin->Init();
143 if (status) {
144 delete hwc_display_builtin;
145 return status;
146 }
147
148 hwc_display_builtin->GetMixerResolution(&builtin_width, &builtin_height);
149 int width = 0, height = 0;
150 HWCDebugHandler::Get()->GetProperty(FB_WIDTH_PROP, &width);
151 HWCDebugHandler::Get()->GetProperty(FB_HEIGHT_PROP, &height);
152 if (width > 0 && height > 0) {
153 builtin_width = UINT32(width);
154 builtin_height = UINT32(height);
155 }
156
157 status = hwc_display_builtin->SetFrameBufferResolution(builtin_width, builtin_height);
158 if (status) {
159 Destroy(hwc_display_builtin);
160 return status;
161 }
162
163 *hwc_display = hwc_display_builtin;
164
165 return status;
166 }
167
Destroy(HWCDisplay * hwc_display)168 void HWCDisplayBuiltIn::Destroy(HWCDisplay *hwc_display) {
169 hwc_display->Deinit();
170 delete hwc_display;
171 }
172
HWCDisplayBuiltIn(CoreInterface * core_intf,BufferAllocator * buffer_allocator,HWCCallbacks * callbacks,HWCDisplayEventHandler * event_handler,qService::QService * qservice,hwc2_display_t id,int32_t sdm_id)173 HWCDisplayBuiltIn::HWCDisplayBuiltIn(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
174 HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
175 qService::QService *qservice, hwc2_display_t id,
176 int32_t sdm_id)
177 : HWCDisplay(core_intf, buffer_allocator, callbacks, event_handler, qservice, kBuiltIn, id,
178 sdm_id, DISPLAY_CLASS_BUILTIN),
179 buffer_allocator_(buffer_allocator),
180 cpu_hint_(NULL), layer_stitch_task_(*this) {
181 }
182
Init()183 int HWCDisplayBuiltIn::Init() {
184 cpu_hint_ = new CPUHint();
185 if (cpu_hint_->Init(static_cast<HWCDebugHandler *>(HWCDebugHandler::Get())) != kErrorNone) {
186 delete cpu_hint_;
187 cpu_hint_ = NULL;
188 }
189
190 use_metadata_refresh_rate_ = true;
191 int disable_metadata_dynfps = 0;
192 HWCDebugHandler::Get()->GetProperty(DISABLE_METADATA_DYNAMIC_FPS_PROP, &disable_metadata_dynfps);
193 if (disable_metadata_dynfps) {
194 use_metadata_refresh_rate_ = false;
195 }
196
197 int status = HWCDisplay::Init();
198 if (status) {
199 return status;
200 }
201 color_mode_ = new HWCColorMode(display_intf_);
202 color_mode_->Init();
203
204 int optimize_refresh = 0;
205 HWCDebugHandler::Get()->GetProperty(ENABLE_OPTIMIZE_REFRESH, &optimize_refresh);
206 enable_optimize_refresh_ = (optimize_refresh == 1);
207 if (enable_optimize_refresh_) {
208 DLOGI("Drop redundant drawcycles %" PRIu64 , id_);
209 }
210
211 int vsyncs = 0;
212 HWCDebugHandler::Get()->GetProperty(DEFER_FPS_FRAME_COUNT, &vsyncs);
213 if (vsyncs > 0) {
214 SetVsyncsApplyRateChange(UINT32(vsyncs));
215 }
216
217 is_primary_ = display_intf_->IsPrimaryDisplay();
218
219 if (is_primary_) {
220 int enable_bw_limits = 0;
221 HWCDebugHandler::Get()->GetProperty(ENABLE_BW_LIMITS, &enable_bw_limits);
222 enable_bw_limits_ = (enable_bw_limits == 1);
223 if (enable_bw_limits_) {
224 DLOGI("Enable BW Limits %" PRIu64, id_);
225 }
226 windowed_display_ = Debug::GetWindowRect(&window_rect_.left, &window_rect_.top,
227 &window_rect_.right, &window_rect_.bottom) != kErrorUndefined;
228 DLOGI("Window rect : [%f %f %f %f]", window_rect_.left, window_rect_.top,
229 window_rect_.right, window_rect_.bottom);
230 }
231
232 uint32_t config_index = 0;
233 GetActiveDisplayConfig(&config_index);
234 DisplayConfigVariableInfo attr = {};
235 GetDisplayAttributesForConfig(INT(config_index), &attr);
236 active_refresh_rate_ = attr.fps;
237
238 DLOGI("active_refresh_rate: %d", active_refresh_rate_);
239
240 return status;
241 }
242
Dump(std::ostringstream * os)243 void HWCDisplayBuiltIn::Dump(std::ostringstream *os) {
244 HWCDisplay::Dump(os);
245 *os << histogram.Dump();
246 }
247
Validate(uint32_t * out_num_types,uint32_t * out_num_requests)248 HWC2::Error HWCDisplayBuiltIn::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
249 auto status = HWC2::Error::None;
250 DisplayError error = kErrorNone;
251
252 DTRACE_SCOPED();
253
254 if (display_paused_ || (!is_primary_ && active_secure_sessions_[kSecureDisplay])) {
255 MarkLayersForGPUBypass();
256 return status;
257 }
258
259 if (color_tranform_failed_) {
260 // Must fall back to client composition
261 MarkLayersForClientComposition();
262 }
263
264 // Fill in the remaining blanks in the layers and add them to the SDM layerstack
265 BuildLayerStack();
266
267 // Add stitch layer to layer stack.
268 AppendStitchLayer();
269
270 // Checks and replaces layer stack for solid fill
271 SolidFillPrepare();
272
273 // Apply current Color Mode and Render Intent.
274 if (color_mode_->ApplyCurrentColorModeWithRenderIntent(
275 static_cast<bool>(layer_stack_.flags.hdr_present)) != HWC2::Error::None) {
276 // Fallback to GPU Composition, if Color Mode can't be applied.
277 MarkLayersForClientComposition();
278 }
279
280 bool pending_output_dump = dump_frame_count_ && dump_output_to_file_;
281
282 if (readback_buffer_queued_ || pending_output_dump) {
283 // RHS values were set in FrameCaptureAsync() called from a binder thread. They are picked up
284 // here in a subsequent draw round. Readback is not allowed for any secure use case.
285 readback_configured_ = !layer_stack_.flags.secure_present;
286 if (readback_configured_) {
287 DisablePartialUpdateOneFrame();
288 layer_stack_.output_buffer = &output_buffer_;
289 layer_stack_.flags.post_processed_output = post_processed_output_;
290 }
291 }
292
293 uint32_t num_updating_layers = GetUpdatingLayersCount();
294 bool one_updating_layer = (num_updating_layers == 1);
295 if (num_updating_layers != 0) {
296 ToggleCPUHint(one_updating_layer);
297 }
298
299 uint32_t refresh_rate = GetOptimalRefreshRate(one_updating_layer);
300 error = display_intf_->SetRefreshRate(refresh_rate, force_refresh_rate_);
301
302 // Get the refresh rate set.
303 display_intf_->GetRefreshRate(&refresh_rate);
304 bool vsync_source = (callbacks_->GetVsyncSource() == id_);
305
306 if (error == kErrorNone) {
307 if (vsync_source && (current_refresh_rate_ < refresh_rate)) {
308 DTRACE_BEGIN("HWC2::Vsync::Enable");
309 // Display is ramping up from idle.
310 // Client realizes need for resync upon change in config.
311 // Since we know config has changed, triggering vsync proactively
312 // can help in reducing pipeline delays to enable events.
313 SetVsyncEnabled(HWC2::Vsync::Enable);
314 DTRACE_END();
315 }
316 // On success, set current refresh rate to new refresh rate.
317 current_refresh_rate_ = refresh_rate;
318 }
319
320 if (layer_set_.empty()) {
321 // Avoid flush for Command mode panel.
322 flush_ = !client_connected_;
323 validated_ = true;
324 return status;
325 }
326
327 status = PrepareLayerStack(out_num_types, out_num_requests);
328 pending_commit_ = true;
329 return status;
330 }
331
CommitLayerStack()332 HWC2::Error HWCDisplayBuiltIn::CommitLayerStack() {
333 skip_commit_ = CanSkipCommit();
334 return HWCDisplay::CommitLayerStack();
335 }
336
CanSkipCommit()337 bool HWCDisplayBuiltIn::CanSkipCommit() {
338 if (layer_stack_invalid_) {
339 return false;
340 }
341
342 // Reject repeated drawcycle requests if it satisfies all conditions.
343 // 1. None of the layerstack attributes changed.
344 // 2. No new buffer latched.
345 // 3. No refresh request triggered by HWC.
346 // 4. This display is not source of vsync.
347 bool buffers_latched = false;
348 for (auto &hwc_layer : layer_set_) {
349 buffers_latched |= hwc_layer->BufferLatched();
350 hwc_layer->ResetBufferFlip();
351 }
352
353 bool vsync_source = (callbacks_->GetVsyncSource() == id_);
354 bool skip_commit = enable_optimize_refresh_ && !pending_commit_ && !buffers_latched &&
355 !pending_refresh_ && !vsync_source;
356 pending_refresh_ = false;
357
358 return skip_commit;
359 }
360
CommitStitchLayers()361 HWC2::Error HWCDisplayBuiltIn::CommitStitchLayers() {
362 if (disable_layer_stitch_) {
363 return HWC2::Error::None;
364 }
365
366 if (!validated_ || skip_commit_) {
367 return HWC2::Error::None;
368 }
369
370 for (auto &layer : layer_stack_.layers) {
371 LayerComposition &composition = layer->composition;
372 if (composition != kCompositionStitch) {
373 continue;
374 }
375
376 LayerStitchContext ctx = {};
377 // Stitch target doesn't have an input fence.
378 // Render all layers at specified destination.
379 LayerBuffer &input_buffer = layer->input_buffer;
380 ctx.src_hnd = reinterpret_cast<const private_handle_t *>(input_buffer.buffer_id);
381 Layer *stitch_layer = stitch_target_->GetSDMLayer();
382 LayerBuffer &output_buffer = stitch_layer->input_buffer;
383 ctx.dst_hnd = reinterpret_cast<const private_handle_t *>(output_buffer.buffer_id);
384 SetRect(layer->stitch_info.dst_rect, &ctx.dst_rect);
385 SetRect(layer->stitch_info.slice_rect, &ctx.scissor_rect);
386 ctx.src_acquire_fence = input_buffer.acquire_fence;
387
388 layer_stitch_task_.PerformTask(LayerStitchTaskCode::kCodeStitch, &ctx);
389
390 // Merge with current fence.
391 output_buffer.acquire_fence = Fence::Merge(output_buffer.acquire_fence, ctx.release_fence);
392 }
393
394 return HWC2::Error::None;
395 }
396
CacheAvrStatus()397 void HWCDisplayBuiltIn::CacheAvrStatus() {
398 QSyncMode qsync_mode = kQSyncModeNone;
399
400 DisplayError error = display_intf_->GetQSyncMode(&qsync_mode);
401 if (error != kErrorNone) {
402 return;
403 }
404
405 bool qsync_enabled = (qsync_mode != kQSyncModeNone);
406 if (qsync_enabled_ != qsync_enabled) {
407 qsync_reconfigured_ = true;
408 qsync_enabled_ = qsync_enabled;
409 } else {
410 qsync_reconfigured_ = false;
411 }
412 }
413
IsQsyncCallbackNeeded(bool * qsync_enabled,int32_t * refresh_rate,int32_t * qsync_refresh_rate)414 bool HWCDisplayBuiltIn::IsQsyncCallbackNeeded(bool *qsync_enabled, int32_t *refresh_rate,
415 int32_t *qsync_refresh_rate) {
416 if (!qsync_reconfigured_) {
417 return false;
418 }
419
420 bool vsync_source = (callbacks_->GetVsyncSource() == id_);
421 // Qsync callback not needed if this display is not the source of vsync
422 if (!vsync_source) {
423 return false;
424 }
425
426 *qsync_enabled = qsync_enabled_;
427 uint32_t current_rate = 0;
428 display_intf_->GetRefreshRate(¤t_rate);
429 *refresh_rate = INT32(current_rate);
430 *qsync_refresh_rate = min_refresh_rate_;
431
432 return true;
433 }
434
GetBwCode(const DisplayConfigVariableInfo & attr)435 int HWCDisplayBuiltIn::GetBwCode(const DisplayConfigVariableInfo &attr) {
436 uint32_t min_refresh_rate = 0, max_refresh_rate = 0;
437 display_intf_->GetRefreshRateRange(&min_refresh_rate, &max_refresh_rate);
438 uint32_t fps = attr.smart_panel ? attr.fps : max_refresh_rate;
439
440 if (fps <= 60) {
441 return kBwLow;
442 } else if (fps <= 90) {
443 return kBwMedium;
444 } else {
445 return kBwHigh;
446 }
447 }
448
SetBwLimitHint(bool enable)449 void HWCDisplayBuiltIn::SetBwLimitHint(bool enable) {
450 if (!enable_bw_limits_) {
451 return;
452 }
453
454 if (!enable) {
455 thermal_bandwidth_client_cancel_request(const_cast<char*>(kDisplayBwName));
456 curr_refresh_rate_ = 0;
457 return;
458 }
459
460 uint32_t config_index = 0;
461 DisplayConfigVariableInfo attr = {};
462 GetActiveDisplayConfig(&config_index);
463 GetDisplayAttributesForConfig(INT(config_index), &attr);
464 if (attr.fps != curr_refresh_rate_ || attr.smart_panel != is_smart_panel_) {
465 int bw_code = GetBwCode(attr);
466 int req_data = thermal_bandwidth_client_merge_input_info(bw_code, 0);
467 int error = thermal_bandwidth_client_request(const_cast<char*>(kDisplayBwName), req_data);
468 if (error) {
469 DLOGE("Thermal bandwidth request failed %d", error);
470 }
471 curr_refresh_rate_ = attr.fps;
472 is_smart_panel_ = attr.smart_panel;
473 }
474 }
475
SetPartialUpdate(DisplayConfigFixedInfo fixed_info)476 void HWCDisplayBuiltIn::SetPartialUpdate(DisplayConfigFixedInfo fixed_info) {
477 partial_update_enabled_ = fixed_info.partial_update || (!fixed_info.is_cmdmode);
478 for (auto hwc_layer : layer_set_) {
479 hwc_layer->SetPartialUpdate(partial_update_enabled_);
480 }
481 client_target_->SetPartialUpdate(partial_update_enabled_);
482 }
483
SetPowerMode(HWC2::PowerMode mode,bool teardown)484 HWC2::Error HWCDisplayBuiltIn::SetPowerMode(HWC2::PowerMode mode, bool teardown) {
485 DisplayConfigFixedInfo fixed_info = {};
486 display_intf_->GetConfig(&fixed_info);
487 bool command_mode = fixed_info.is_cmdmode;
488
489 auto status = HWCDisplay::SetPowerMode(mode, teardown);
490 if (status != HWC2::Error::None) {
491 return status;
492 }
493
494 display_intf_->GetConfig(&fixed_info);
495 is_cmd_mode_ = fixed_info.is_cmdmode;
496 if (is_cmd_mode_ != command_mode) {
497 SetPartialUpdate(fixed_info);
498 }
499
500 if (mode == HWC2::PowerMode::Off) {
501 SetBwLimitHint(false);
502 }
503
504 return HWC2::Error::None;
505 }
506
Present(shared_ptr<Fence> * out_retire_fence)507 HWC2::Error HWCDisplayBuiltIn::Present(shared_ptr<Fence> *out_retire_fence) {
508 auto status = HWC2::Error::None;
509
510 DTRACE_SCOPED();
511
512 if (!is_primary_ && active_secure_sessions_[kSecureDisplay]) {
513 return status;
514 } else if (display_paused_) {
515 DisplayError error = display_intf_->Flush(&layer_stack_);
516 validated_ = false;
517 if (error != kErrorNone) {
518 DLOGE("Flush failed. Error = %d", error);
519 }
520 } else {
521 CacheAvrStatus();
522 DisplayConfigFixedInfo fixed_info = {};
523 display_intf_->GetConfig(&fixed_info);
524 bool command_mode = fixed_info.is_cmdmode;
525
526 status = CommitStitchLayers();
527 if (status != HWC2::Error::None) {
528 DLOGE("Stitch failed: %d", status);
529 return status;
530 }
531
532 status = CommitLayerStack();
533 if (status == HWC2::Error::None) {
534 HandleFrameOutput();
535 PostCommitStitchLayers();
536 status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
537 SetBwLimitHint(true);
538 display_intf_->GetConfig(&fixed_info);
539 is_cmd_mode_ = fixed_info.is_cmdmode;
540 if (is_cmd_mode_ != command_mode) {
541 SetPartialUpdate(fixed_info);
542 }
543 }
544 }
545
546 if (CC_UNLIKELY(!has_config_hbm_threshold_)) {
547 uint32_t panel_x, panel_y;
548 GetPanelResolution(&panel_x, &panel_y);
549 hbm_threshold_px_ = float(panel_x * panel_y) * hbm_threshold_pct_;
550 DLOGI("Configure hbm_threshold_px_ to %f", hbm_threshold_px_);
551
552 has_config_hbm_threshold_ = true;
553 }
554
555 const bool enable_hbm(hdr_largest_layer_px_ > hbm_threshold_px_);
556 if (high_brightness_mode_ != enable_hbm) {
557 HbmState state = enable_hbm ? HbmState::HDR : HbmState::OFF;
558 auto status = SetHbm(state, HWC);
559 if (status == HWC2::Error::None) {
560 high_brightness_mode_ = enable_hbm;
561 } else {
562 DLOGE("failed to setHbm to %d", enable_hbm);
563 }
564 }
565
566 pending_commit_ = false;
567 return status;
568 }
569
PostCommitStitchLayers()570 void HWCDisplayBuiltIn::PostCommitStitchLayers() {
571 if (disable_layer_stitch_) {
572 return;
573 }
574
575 // Close Stitch buffer acquire fence.
576 Layer *stitch_layer = stitch_target_->GetSDMLayer();
577 LayerBuffer &output_buffer = stitch_layer->input_buffer;
578 for (auto &layer : layer_stack_.layers) {
579 LayerComposition &composition = layer->composition;
580 if (composition != kCompositionStitch) {
581 continue;
582 }
583 LayerBuffer &input_buffer = layer->input_buffer;
584 input_buffer.release_fence = output_buffer.acquire_fence;
585 }
586 }
587
GetColorModes(uint32_t * out_num_modes,ColorMode * out_modes)588 HWC2::Error HWCDisplayBuiltIn::GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes) {
589 if (out_modes == nullptr) {
590 *out_num_modes = color_mode_->GetColorModeCount();
591 } else {
592 color_mode_->GetColorModes(out_num_modes, out_modes);
593 }
594
595 return HWC2::Error::None;
596 }
597
GetRenderIntents(ColorMode mode,uint32_t * out_num_intents,RenderIntent * out_intents)598 HWC2::Error HWCDisplayBuiltIn::GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
599 RenderIntent *out_intents) {
600 if (out_intents == nullptr) {
601 *out_num_intents = color_mode_->GetRenderIntentCount(mode);
602 } else {
603 color_mode_->GetRenderIntents(mode, out_num_intents, out_intents);
604 }
605 return HWC2::Error::None;
606 }
607
SetColorMode(ColorMode mode)608 HWC2::Error HWCDisplayBuiltIn::SetColorMode(ColorMode mode) {
609 return SetColorModeWithRenderIntent(mode, RenderIntent::COLORIMETRIC);
610 }
611
SetColorModeWithRenderIntent(ColorMode mode,RenderIntent intent)612 HWC2::Error HWCDisplayBuiltIn::SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
613 auto status = color_mode_->CacheColorModeWithRenderIntent(mode, intent);
614 if (status != HWC2::Error::None) {
615 DLOGE("failed for mode = %d intent = %d", mode, intent);
616 return status;
617 }
618 callbacks_->Refresh(id_);
619 validated_ = false;
620 return status;
621 }
622
SetColorModeById(int32_t color_mode_id)623 HWC2::Error HWCDisplayBuiltIn::SetColorModeById(int32_t color_mode_id) {
624 auto status = color_mode_->SetColorModeById(color_mode_id);
625 if (status != HWC2::Error::None) {
626 DLOGE("failed for mode = %d", color_mode_id);
627 return status;
628 }
629
630 callbacks_->Refresh(id_);
631 validated_ = false;
632
633 return status;
634 }
635
SetColorModeFromClientApi(int32_t color_mode_id)636 HWC2::Error HWCDisplayBuiltIn::SetColorModeFromClientApi(int32_t color_mode_id) {
637 DisplayError error = kErrorNone;
638 std::string mode_string;
639
640 error = display_intf_->GetColorModeName(color_mode_id, &mode_string);
641 if (error) {
642 DLOGE("Failed to get mode name for mode %d", color_mode_id);
643 return HWC2::Error::BadParameter;
644 }
645
646 auto status = color_mode_->SetColorModeFromClientApi(mode_string);
647 if (status != HWC2::Error::None) {
648 DLOGE("Failed to set mode = %d", color_mode_id);
649 return status;
650 }
651
652 return status;
653 }
654
RestoreColorTransform()655 HWC2::Error HWCDisplayBuiltIn::RestoreColorTransform() {
656 auto status = color_mode_->RestoreColorTransform();
657 if (status != HWC2::Error::None) {
658 DLOGE("failed to RestoreColorTransform");
659 return status;
660 }
661
662 callbacks_->Refresh(id_);
663
664 return status;
665 }
666
SetColorTransform(const float * matrix,android_color_transform_t hint)667 HWC2::Error HWCDisplayBuiltIn::SetColorTransform(const float *matrix,
668 android_color_transform_t hint) {
669 if (!matrix) {
670 return HWC2::Error::BadParameter;
671 }
672
673 auto status = color_mode_->SetColorTransform(matrix, hint);
674 if (status != HWC2::Error::None) {
675 DLOGE("failed for hint = %d", hint);
676 color_tranform_failed_ = true;
677 return status;
678 }
679
680 callbacks_->Refresh(id_);
681 color_tranform_failed_ = false;
682 validated_ = false;
683
684 return status;
685 }
686
SetReadbackBuffer(const native_handle_t * buffer,shared_ptr<Fence> acquire_fence,bool post_processed_output,CWBClient client)687 HWC2::Error HWCDisplayBuiltIn::SetReadbackBuffer(const native_handle_t *buffer,
688 shared_ptr<Fence> acquire_fence,
689 bool post_processed_output, CWBClient client) {
690 if (cwb_client_ != client && cwb_client_ != kCWBClientNone) {
691 DLOGE("CWB is in use with client = %d", cwb_client_);
692 return HWC2::Error::NoResources;
693 }
694
695 const private_handle_t *handle = reinterpret_cast<const private_handle_t *>(buffer);
696 if (!handle || (handle->fd < 0)) {
697 return HWC2::Error::BadParameter;
698 }
699
700 // Configure the output buffer as Readback buffer
701 output_buffer_.width = UINT32(handle->width);
702 output_buffer_.height = UINT32(handle->height);
703 output_buffer_.unaligned_width = UINT32(handle->unaligned_width);
704 output_buffer_.unaligned_height = UINT32(handle->unaligned_height);
705 output_buffer_.format = HWCLayer::GetSDMFormat(handle->format, handle->flags);
706 output_buffer_.planes[0].fd = handle->fd;
707 output_buffer_.planes[0].stride = UINT32(handle->width);
708 output_buffer_.acquire_fence = acquire_fence;
709 output_buffer_.handle_id = handle->id;
710
711 post_processed_output_ = post_processed_output;
712 readback_buffer_queued_ = true;
713 readback_configured_ = false;
714 validated_ = false;
715 cwb_client_ = client;
716
717 return HWC2::Error::None;
718 }
719
GetReadbackBufferFence(shared_ptr<Fence> * release_fence)720 HWC2::Error HWCDisplayBuiltIn::GetReadbackBufferFence(shared_ptr<Fence> *release_fence) {
721 auto status = HWC2::Error::None;
722
723 if (readback_configured_ && output_buffer_.release_fence) {
724 *release_fence = output_buffer_.release_fence;
725 } else {
726 status = HWC2::Error::Unsupported;
727 }
728
729 post_processed_output_ = false;
730 readback_buffer_queued_ = false;
731 readback_configured_ = false;
732 output_buffer_ = {};
733 cwb_client_ = kCWBClientNone;
734
735 return status;
736 }
737
TeardownConcurrentWriteback(void)738 DisplayError HWCDisplayBuiltIn::TeardownConcurrentWriteback(void) {
739 DisplayError error = kErrorNotSupported;
740 if (Fence::Wait(output_buffer_.release_fence) != kErrorNone) {
741 DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
742 return kErrorResources;
743 }
744
745 if (display_intf_) {
746 error = display_intf_->TeardownConcurrentWriteback();
747 }
748
749 return error;
750 }
751
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)752 HWC2::Error HWCDisplayBuiltIn::SetDisplayDppsAdROI(uint32_t h_start, uint32_t h_end,
753 uint32_t v_start, uint32_t v_end,
754 uint32_t factor_in, uint32_t factor_out) {
755 DisplayError error = kErrorNone;
756 DisplayDppsAd4RoiCfg dpps_ad4_roi_cfg = {};
757 uint32_t panel_width = 0, panel_height = 0;
758 constexpr uint16_t kMaxFactorVal = 0xffff;
759
760 if (h_start >= h_end || v_start >= v_end || factor_in > kMaxFactorVal ||
761 factor_out > kMaxFactorVal) {
762 DLOGE("Invalid roi region = [%u, %u, %u, %u, %u, %u]",
763 h_start, h_end, v_start, v_end, factor_in, factor_out);
764 return HWC2::Error::BadParameter;
765 }
766
767 GetPanelResolution(&panel_width, &panel_height);
768
769 if (h_start >= panel_width || h_end > panel_width ||
770 v_start >= panel_height || v_end > panel_height) {
771 DLOGE("Invalid roi region = [%u, %u, %u, %u], panel resolution = [%u, %u]",
772 h_start, h_end, v_start, v_end, panel_width, panel_height);
773 return HWC2::Error::BadParameter;
774 }
775
776 dpps_ad4_roi_cfg.h_start = h_start;
777 dpps_ad4_roi_cfg.h_end = h_end;
778 dpps_ad4_roi_cfg.v_start = v_start;
779 dpps_ad4_roi_cfg.v_end = v_end;
780 dpps_ad4_roi_cfg.factor_in = factor_in;
781 dpps_ad4_roi_cfg.factor_out = factor_out;
782
783 error = display_intf_->SetDisplayDppsAdROI(&dpps_ad4_roi_cfg);
784 if (error)
785 return HWC2::Error::BadConfig;
786
787 callbacks_->Refresh(id_);
788
789 return HWC2::Error::None;
790 }
791
SetFrameTriggerMode(uint32_t mode)792 HWC2::Error HWCDisplayBuiltIn::SetFrameTriggerMode(uint32_t mode) {
793 DisplayError error = kErrorNone;
794 FrameTriggerMode trigger_mode = kFrameTriggerDefault;
795
796 if (mode >= kFrameTriggerMax) {
797 DLOGE("Invalid input mode %d", mode);
798 return HWC2::Error::BadParameter;
799 }
800
801 trigger_mode = static_cast<FrameTriggerMode>(mode);
802 error = display_intf_->SetFrameTriggerMode(trigger_mode);
803 if (error)
804 return HWC2::Error::BadConfig;
805
806 callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
807 validated_ = false;
808
809 return HWC2::Error::None;
810 }
811
Perform(uint32_t operation,...)812 int HWCDisplayBuiltIn::Perform(uint32_t operation, ...) {
813 va_list args;
814 va_start(args, operation);
815 int val = 0;
816 LayerSolidFill *solid_fill_color;
817 LayerRect *rect = NULL;
818
819 switch (operation) {
820 case SET_METADATA_DYN_REFRESH_RATE:
821 val = va_arg(args, int32_t);
822 SetMetaDataRefreshRateFlag(val);
823 break;
824 case SET_BINDER_DYN_REFRESH_RATE:
825 val = va_arg(args, int32_t);
826 ForceRefreshRate(UINT32(val));
827 break;
828 case SET_DISPLAY_MODE:
829 val = va_arg(args, int32_t);
830 SetDisplayMode(UINT32(val));
831 break;
832 case SET_QDCM_SOLID_FILL_INFO:
833 solid_fill_color = va_arg(args, LayerSolidFill*);
834 SetQDCMSolidFillInfo(true, *solid_fill_color);
835 break;
836 case UNSET_QDCM_SOLID_FILL_INFO:
837 solid_fill_color = va_arg(args, LayerSolidFill*);
838 SetQDCMSolidFillInfo(false, *solid_fill_color);
839 break;
840 case SET_QDCM_SOLID_FILL_RECT:
841 rect = va_arg(args, LayerRect*);
842 solid_fill_rect_ = *rect;
843 break;
844 default:
845 DLOGW("Invalid operation %d", operation);
846 va_end(args);
847 return -EINVAL;
848 }
849 va_end(args);
850 validated_ = false;
851
852 return 0;
853 }
854
SetDisplayMode(uint32_t mode)855 DisplayError HWCDisplayBuiltIn::SetDisplayMode(uint32_t mode) {
856 DisplayError error = kErrorNone;
857
858 if (display_intf_) {
859 error = display_intf_->SetDisplayMode(mode);
860 if (error == kErrorNone) {
861 DisplayConfigFixedInfo fixed_info = {};
862 display_intf_->GetConfig(&fixed_info);
863 is_cmd_mode_ = fixed_info.is_cmdmode;
864 partial_update_enabled_ = fixed_info.partial_update;
865 for (auto hwc_layer : layer_set_) {
866 hwc_layer->SetPartialUpdate(partial_update_enabled_);
867 }
868 client_target_->SetPartialUpdate(partial_update_enabled_);
869 }
870 }
871
872 return error;
873 }
874
SetMetaDataRefreshRateFlag(bool enable)875 void HWCDisplayBuiltIn::SetMetaDataRefreshRateFlag(bool enable) {
876 int disable_metadata_dynfps = 0;
877
878 HWCDebugHandler::Get()->GetProperty(DISABLE_METADATA_DYNAMIC_FPS_PROP, &disable_metadata_dynfps);
879 if (disable_metadata_dynfps) {
880 return;
881 }
882 use_metadata_refresh_rate_ = enable;
883 }
884
SetQDCMSolidFillInfo(bool enable,const LayerSolidFill & color)885 void HWCDisplayBuiltIn::SetQDCMSolidFillInfo(bool enable, const LayerSolidFill &color) {
886 solid_fill_enable_ = enable;
887 solid_fill_color_ = color;
888 }
889
ToggleCPUHint(bool set)890 void HWCDisplayBuiltIn::ToggleCPUHint(bool set) {
891 if (!cpu_hint_) {
892 return;
893 }
894
895 if (set) {
896 cpu_hint_->Set();
897 } else {
898 cpu_hint_->Reset();
899 }
900 }
901
HandleSecureSession(const std::bitset<kSecureMax> & secure_sessions,bool * power_on_pending)902 int HWCDisplayBuiltIn::HandleSecureSession(const std::bitset<kSecureMax> &secure_sessions,
903 bool *power_on_pending) {
904 if (!power_on_pending) {
905 return -EINVAL;
906 }
907
908 if (!is_primary_) {
909 return HWCDisplay::HandleSecureSession(secure_sessions, power_on_pending);
910 }
911
912 if (current_power_mode_ != HWC2::PowerMode::On) {
913 return 0;
914 }
915
916 if (active_secure_sessions_[kSecureDisplay] != secure_sessions[kSecureDisplay]) {
917 SecureEvent secure_event =
918 secure_sessions.test(kSecureDisplay) ? kSecureDisplayStart : kSecureDisplayEnd;
919 DisplayError err = display_intf_->HandleSecureEvent(secure_event, &layer_stack_);
920 if (err != kErrorNone) {
921 DLOGE("Set secure event failed");
922 return err;
923 }
924
925 DLOGI("SecureDisplay state changed from %d to %d for display %" PRIu64 "-%d",
926 active_secure_sessions_.test(kSecureDisplay), secure_sessions.test(kSecureDisplay),
927 id_, type_);
928 }
929 active_secure_sessions_ = secure_sessions;
930 *power_on_pending = false;
931 return 0;
932 }
933
ForceRefreshRate(uint32_t refresh_rate)934 void HWCDisplayBuiltIn::ForceRefreshRate(uint32_t refresh_rate) {
935 if ((refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) ||
936 force_refresh_rate_ == refresh_rate) {
937 // Cannot honor force refresh rate, as its beyond the range or new request is same
938 return;
939 }
940
941 force_refresh_rate_ = refresh_rate;
942
943 callbacks_->Refresh(id_);
944
945 return;
946 }
947
GetOptimalRefreshRate(bool one_updating_layer)948 uint32_t HWCDisplayBuiltIn::GetOptimalRefreshRate(bool one_updating_layer) {
949 if (force_refresh_rate_) {
950 return force_refresh_rate_;
951 } else if (use_metadata_refresh_rate_ && one_updating_layer && metadata_refresh_rate_) {
952 return metadata_refresh_rate_;
953 }
954
955 DLOGV_IF(kTagClient, "active_refresh_rate_: %d", active_refresh_rate_);
956 return active_refresh_rate_;
957 }
958
SetIdleTimeoutMs(uint32_t timeout_ms)959 void HWCDisplayBuiltIn::SetIdleTimeoutMs(uint32_t timeout_ms) {
960 display_intf_->SetIdleTimeoutMs(timeout_ms);
961 validated_ = false;
962 }
963
HandleFrameOutput()964 void HWCDisplayBuiltIn::HandleFrameOutput() {
965 if (readback_buffer_queued_) {
966 validated_ = false;
967 }
968
969 if (frame_capture_buffer_queued_) {
970 HandleFrameCapture();
971 } else if (dump_output_to_file_) {
972 HandleFrameDump();
973 }
974 }
975
HandleFrameCapture()976 void HWCDisplayBuiltIn::HandleFrameCapture() {
977 if (readback_configured_ && output_buffer_.release_fence) {
978 frame_capture_status_ = Fence::Wait(output_buffer_.release_fence);
979 }
980
981 frame_capture_buffer_queued_ = false;
982 readback_buffer_queued_ = false;
983 post_processed_output_ = false;
984 readback_configured_ = false;
985 output_buffer_ = {};
986 cwb_client_ = kCWBClientNone;
987 }
988
HandleFrameDump()989 void HWCDisplayBuiltIn::HandleFrameDump() {
990 if (dump_frame_count_) {
991 int ret = 0;
992 ret = Fence::Wait(output_buffer_.release_fence);
993 if (ret != kErrorNone) {
994 DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
995 }
996
997 if (!ret) {
998 DumpOutputBuffer(output_buffer_info_, output_buffer_base_, layer_stack_.retire_fence);
999 validated_ = false;
1000 }
1001
1002 if (0 == (dump_frame_count_ - 1)) {
1003 dump_output_to_file_ = false;
1004 // Unmap and Free buffer
1005 if (munmap(output_buffer_base_, output_buffer_info_.alloc_buffer_info.size) != 0) {
1006 DLOGE("unmap failed with err %d", errno);
1007 }
1008 if (buffer_allocator_->FreeBuffer(&output_buffer_info_) != 0) {
1009 DLOGE("FreeBuffer failed");
1010 }
1011
1012 readback_buffer_queued_ = false;
1013 post_processed_output_ = false;
1014 readback_configured_ = false;
1015
1016 output_buffer_ = {};
1017 output_buffer_info_ = {};
1018 output_buffer_base_ = nullptr;
1019 cwb_client_ = kCWBClientNone;
1020 }
1021 }
1022 }
1023
SetFrameDumpConfig(uint32_t count,uint32_t bit_mask_layer_type,int32_t format,bool post_processed)1024 HWC2::Error HWCDisplayBuiltIn::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type,
1025 int32_t format, bool post_processed) {
1026 HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type, format, post_processed);
1027 dump_output_to_file_ = bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP);
1028 DLOGI("output_layer_dump_enable %d", dump_output_to_file_);
1029
1030 if (dump_output_to_file_) {
1031 if (cwb_client_ != kCWBClientNone) {
1032 DLOGW("CWB is in use with client = %d", cwb_client_);
1033 return HWC2::Error::NoResources;
1034 }
1035 }
1036
1037 if (!count || !dump_output_to_file_ || (output_buffer_info_.alloc_buffer_info.fd >= 0)) {
1038 return HWC2::Error::None;
1039 }
1040
1041 // Allocate and map output buffer
1042 if (post_processed) {
1043 // To dump post-processed (DSPP) output, use Panel resolution.
1044 GetPanelResolution(&output_buffer_info_.buffer_config.width,
1045 &output_buffer_info_.buffer_config.height);
1046 } else {
1047 // To dump Layer Mixer output, use FrameBuffer resolution.
1048 GetFrameBufferResolution(&output_buffer_info_.buffer_config.width,
1049 &output_buffer_info_.buffer_config.height);
1050 }
1051
1052 output_buffer_info_.buffer_config.format = HWCLayer::GetSDMFormat(format, 0);
1053 output_buffer_info_.buffer_config.buffer_count = 1;
1054 if (buffer_allocator_->AllocateBuffer(&output_buffer_info_) != 0) {
1055 DLOGE("Buffer allocation failed");
1056 output_buffer_info_ = {};
1057 return HWC2::Error::NoResources;
1058 }
1059
1060 void *buffer = mmap(NULL, output_buffer_info_.alloc_buffer_info.size, PROT_READ | PROT_WRITE,
1061 MAP_SHARED, output_buffer_info_.alloc_buffer_info.fd, 0);
1062
1063 if (buffer == MAP_FAILED) {
1064 DLOGE("mmap failed with err %d", errno);
1065 buffer_allocator_->FreeBuffer(&output_buffer_info_);
1066 output_buffer_info_ = {};
1067 return HWC2::Error::NoResources;
1068 }
1069
1070 output_buffer_base_ = buffer;
1071 const native_handle_t *handle = static_cast<native_handle_t *>(output_buffer_info_.private_data);
1072 SetReadbackBuffer(handle, nullptr, post_processed, kCWBClientFrameDump);
1073
1074 return HWC2::Error::None;
1075 }
1076
FrameCaptureAsync(const BufferInfo & output_buffer_info,bool post_processed_output)1077 int HWCDisplayBuiltIn::FrameCaptureAsync(const BufferInfo &output_buffer_info,
1078 bool post_processed_output) {
1079 if (cwb_client_ != kCWBClientNone) {
1080 DLOGE("CWB is in use with client = %d", cwb_client_);
1081 return -1;
1082 }
1083
1084 // Note: This function is called in context of a binder thread and a lock is already held
1085 if (output_buffer_info.alloc_buffer_info.fd < 0) {
1086 DLOGE("Invalid fd %d", output_buffer_info.alloc_buffer_info.fd);
1087 return -1;
1088 }
1089
1090 auto panel_width = 0u;
1091 auto panel_height = 0u;
1092 auto fb_width = 0u;
1093 auto fb_height = 0u;
1094
1095 GetPanelResolution(&panel_width, &panel_height);
1096 GetFrameBufferResolution(&fb_width, &fb_height);
1097
1098 if (post_processed_output && (output_buffer_info.buffer_config.width < panel_width ||
1099 output_buffer_info.buffer_config.height < panel_height)) {
1100 DLOGE("Buffer dimensions should not be less than panel resolution");
1101 return -1;
1102 } else if (!post_processed_output && (output_buffer_info.buffer_config.width < fb_width ||
1103 output_buffer_info.buffer_config.height < fb_height)) {
1104 DLOGE("Buffer dimensions should not be less than FB resolution");
1105 return -1;
1106 }
1107
1108 const native_handle_t *buffer = static_cast<native_handle_t *>(output_buffer_info.private_data);
1109 SetReadbackBuffer(buffer, nullptr, post_processed_output, kCWBClientColor);
1110 frame_capture_buffer_queued_ = true;
1111 frame_capture_status_ = -EAGAIN;
1112
1113 return 0;
1114 }
1115
SetDetailEnhancerConfig(const DisplayDetailEnhancerData & de_data)1116 DisplayError HWCDisplayBuiltIn::SetDetailEnhancerConfig
1117 (const DisplayDetailEnhancerData &de_data) {
1118 DisplayError error = kErrorNotSupported;
1119
1120 if (display_intf_) {
1121 error = display_intf_->SetDetailEnhancerData(de_data);
1122 validated_ = false;
1123 }
1124 return error;
1125 }
1126
ControlPartialUpdate(bool enable,uint32_t * pending)1127 DisplayError HWCDisplayBuiltIn::ControlPartialUpdate(bool enable, uint32_t *pending) {
1128 DisplayError error = kErrorNone;
1129
1130 if (display_intf_) {
1131 error = display_intf_->ControlPartialUpdate(enable, pending);
1132 validated_ = false;
1133 }
1134
1135 return error;
1136 }
1137
DisablePartialUpdateOneFrame()1138 DisplayError HWCDisplayBuiltIn::DisablePartialUpdateOneFrame() {
1139 DisplayError error = kErrorNone;
1140
1141 if (display_intf_) {
1142 error = display_intf_->DisablePartialUpdateOneFrame();
1143 validated_ = false;
1144 }
1145
1146 return error;
1147 }
1148
SetDisplayedContentSamplingEnabledVndService(bool enabled)1149 HWC2::Error HWCDisplayBuiltIn::SetDisplayedContentSamplingEnabledVndService(bool enabled) {
1150 std::unique_lock<decltype(sampling_mutex)> lk(sampling_mutex);
1151 vndservice_sampling_vote = enabled;
1152 if (api_sampling_vote || vndservice_sampling_vote) {
1153 histogram.start();
1154 display_intf_->colorSamplingOn();
1155 } else {
1156 display_intf_->colorSamplingOff();
1157 histogram.stop();
1158 }
1159 return HWC2::Error::None;
1160 }
1161
SetDisplayedContentSamplingEnabled(int32_t enabled,uint8_t component_mask,uint64_t max_frames)1162 HWC2::Error HWCDisplayBuiltIn::SetDisplayedContentSamplingEnabled(int32_t enabled,
1163 uint8_t component_mask,
1164 uint64_t max_frames) {
1165 if ((enabled != HWC2_DISPLAYED_CONTENT_SAMPLING_ENABLE) &&
1166 (enabled != HWC2_DISPLAYED_CONTENT_SAMPLING_DISABLE))
1167 return HWC2::Error::BadParameter;
1168
1169 std::unique_lock<decltype(sampling_mutex)> lk(sampling_mutex);
1170 if (enabled == HWC2_DISPLAYED_CONTENT_SAMPLING_ENABLE) {
1171 api_sampling_vote = true;
1172 } else {
1173 api_sampling_vote = false;
1174 }
1175
1176 auto start = api_sampling_vote || vndservice_sampling_vote;
1177 if (start && max_frames == 0) {
1178 histogram.start();
1179 display_intf_->colorSamplingOn();
1180 } else if (start) {
1181 histogram.start(max_frames);
1182 display_intf_->colorSamplingOn();
1183 } else {
1184 display_intf_->colorSamplingOff();
1185 histogram.stop();
1186 }
1187 return HWC2::Error::None;
1188 }
1189
GetDisplayedContentSamplingAttributes(int32_t * format,int32_t * dataspace,uint8_t * supported_components)1190 HWC2::Error HWCDisplayBuiltIn::GetDisplayedContentSamplingAttributes(
1191 int32_t *format, int32_t *dataspace, uint8_t *supported_components) {
1192 return histogram.getAttributes(format, dataspace, supported_components);
1193 }
1194
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])1195 HWC2::Error HWCDisplayBuiltIn::GetDisplayedContentSample(
1196 uint64_t max_frames, uint64_t timestamp, uint64_t *numFrames,
1197 int32_t samples_size[NUM_HISTOGRAM_COLOR_COMPONENTS],
1198 uint64_t *samples[NUM_HISTOGRAM_COLOR_COMPONENTS]) {
1199 histogram.collect(max_frames, timestamp, samples_size, samples, numFrames);
1200 return HWC2::Error::None;
1201 }
1202
SetMixerResolution(uint32_t width,uint32_t height)1203 DisplayError HWCDisplayBuiltIn::SetMixerResolution(uint32_t width, uint32_t height) {
1204 DisplayError error = display_intf_->SetMixerResolution(width, height);
1205 callbacks_->Refresh(id_);
1206 validated_ = false;
1207 return error;
1208 }
1209
GetMixerResolution(uint32_t * width,uint32_t * height)1210 DisplayError HWCDisplayBuiltIn::GetMixerResolution(uint32_t *width, uint32_t *height) {
1211 return display_intf_->GetMixerResolution(width, height);
1212 }
1213
SetQSyncMode(QSyncMode qsync_mode)1214 HWC2::Error HWCDisplayBuiltIn::SetQSyncMode(QSyncMode qsync_mode) {
1215 // Client needs to ensure that config change and qsync mode change
1216 // are not triggered in the same drawcycle.
1217 if (pending_config_) {
1218 DLOGE("Failed to set qsync mode. Pending active config transition");
1219 return HWC2::Error::Unsupported;
1220 }
1221
1222 auto err = display_intf_->SetQSyncMode(qsync_mode);
1223 if (err != kErrorNone) {
1224 return HWC2::Error::Unsupported;
1225 }
1226
1227 validated_ = false;
1228 return HWC2::Error::None;
1229 }
1230
ControlIdlePowerCollapse(bool enable,bool synchronous)1231 DisplayError HWCDisplayBuiltIn::ControlIdlePowerCollapse(bool enable, bool synchronous) {
1232 DisplayError error = kErrorNone;
1233
1234 if (display_intf_) {
1235 error = display_intf_->ControlIdlePowerCollapse(enable, synchronous);
1236 validated_ = false;
1237 }
1238 return error;
1239 }
1240
SetDynamicDSIClock(uint64_t bitclk)1241 DisplayError HWCDisplayBuiltIn::SetDynamicDSIClock(uint64_t bitclk) {
1242 DisablePartialUpdateOneFrame();
1243 DisplayError error = display_intf_->SetDynamicDSIClock(bitclk);
1244 if (error != kErrorNone) {
1245 DLOGE(" failed: Clk: %" PRIu64 " Error: %d", bitclk, error);
1246 return error;
1247 }
1248
1249 callbacks_->Refresh(id_);
1250 validated_ = false;
1251
1252 return kErrorNone;
1253 }
1254
GetDynamicDSIClock(uint64_t * bitclk)1255 DisplayError HWCDisplayBuiltIn::GetDynamicDSIClock(uint64_t *bitclk) {
1256 if (display_intf_) {
1257 return display_intf_->GetDynamicDSIClock(bitclk);
1258 }
1259
1260 return kErrorNotSupported;
1261 }
1262
GetSupportedDSIClock(std::vector<uint64_t> * bitclk_rates)1263 DisplayError HWCDisplayBuiltIn::GetSupportedDSIClock(std::vector<uint64_t> *bitclk_rates) {
1264 if (display_intf_) {
1265 return display_intf_->GetSupportedDSIClock(bitclk_rates);
1266 }
1267
1268 return kErrorNotSupported;
1269 }
1270
UpdateDisplayId(hwc2_display_t id)1271 HWC2::Error HWCDisplayBuiltIn::UpdateDisplayId(hwc2_display_t id) {
1272 id_ = id;
1273 return HWC2::Error::None;
1274 }
1275
SetPendingRefresh()1276 HWC2::Error HWCDisplayBuiltIn::SetPendingRefresh() {
1277 pending_refresh_ = true;
1278 return HWC2::Error::None;
1279 }
1280
SetPanelBrightness(float brightness)1281 HWC2::Error HWCDisplayBuiltIn::SetPanelBrightness(float brightness) {
1282 DisplayError ret = display_intf_->SetPanelBrightness(brightness);
1283 if (ret != kErrorNone) {
1284 return HWC2::Error::NoResources;
1285 }
1286
1287 return HWC2::Error::None;
1288 }
1289
GetPanelBrightness(float * brightness)1290 HWC2::Error HWCDisplayBuiltIn::GetPanelBrightness(float *brightness) {
1291 DisplayError ret = display_intf_->GetPanelBrightness(brightness);
1292 if (ret != kErrorNone) {
1293 return HWC2::Error::NoResources;
1294 }
1295
1296 return HWC2::Error::None;
1297 }
1298
GetPanelMaxBrightness(uint32_t * max_brightness_level)1299 HWC2::Error HWCDisplayBuiltIn::GetPanelMaxBrightness(uint32_t *max_brightness_level) {
1300 DisplayError ret = display_intf_->GetPanelMaxBrightness(max_brightness_level);
1301 if (ret != kErrorNone) {
1302 return HWC2::Error::NoResources;
1303 }
1304
1305 return HWC2::Error::None;
1306 }
1307
SetCurrentPanelGammaSource(enum PanelGammaSource source)1308 DisplayError HWCDisplayBuiltIn::SetCurrentPanelGammaSource(enum PanelGammaSource source) {
1309 DisplayError error = UpdatePanelGammaTable(source);
1310 if (error == kErrorNone) {
1311 current_panel_gamma_source_ = source;
1312 }
1313
1314 return error;
1315 }
1316
SetBLScale(uint32_t level)1317 HWC2::Error HWCDisplayBuiltIn::SetBLScale(uint32_t level) {
1318 DisplayError ret = display_intf_->SetBLScale(level);
1319 if (ret != kErrorNone) {
1320 return HWC2::Error::NoResources;
1321 }
1322 return HWC2::Error::None;
1323 }
1324
UpdatePowerMode(HWC2::PowerMode mode)1325 HWC2::Error HWCDisplayBuiltIn::UpdatePowerMode(HWC2::PowerMode mode) {
1326 current_power_mode_ = mode;
1327 validated_ = false;
1328 return HWC2::Error::None;
1329 }
1330
SetClientTarget(buffer_handle_t target,shared_ptr<Fence> acquire_fence,int32_t dataspace,hwc_region_t damage)1331 HWC2::Error HWCDisplayBuiltIn::SetClientTarget(buffer_handle_t target,
1332 shared_ptr<Fence> acquire_fence,
1333 int32_t dataspace, hwc_region_t damage) {
1334 HWC2::Error error = HWCDisplay::SetClientTarget(target, acquire_fence, dataspace, damage);
1335 if (error != HWC2::Error::None) {
1336 return error;
1337 }
1338
1339 // windowed_display and dynamic scaling are not supported.
1340 if (windowed_display_) {
1341 return HWC2::Error::None;
1342 }
1343
1344 Layer *sdm_layer = client_target_->GetSDMLayer();
1345 uint32_t fb_width = 0, fb_height = 0;
1346
1347 GetFrameBufferResolution(&fb_width, &fb_height);
1348
1349 if (fb_width != sdm_layer->input_buffer.unaligned_width ||
1350 fb_height != sdm_layer->input_buffer.unaligned_height) {
1351 if (SetFrameBufferConfig(sdm_layer->input_buffer.unaligned_width,
1352 sdm_layer->input_buffer.unaligned_height)) {
1353 return HWC2::Error::BadParameter;
1354 }
1355 }
1356
1357 return HWC2::Error::None;
1358 }
1359
IsSmartPanelConfig(uint32_t config_id)1360 bool HWCDisplayBuiltIn::IsSmartPanelConfig(uint32_t config_id) {
1361 if (config_id < hwc_config_map_.size()) {
1362 uint32_t index = hwc_config_map_.at(config_id);
1363 return variable_config_map_.at(index).smart_panel;
1364 }
1365
1366 return false;
1367 }
1368
HasSmartPanelConfig(void)1369 bool HWCDisplayBuiltIn::HasSmartPanelConfig(void) {
1370 for (auto &config : variable_config_map_) {
1371 if (config.second.smart_panel) {
1372 return true;
1373 }
1374 }
1375
1376 return false;
1377 }
1378
Deinit()1379 int HWCDisplayBuiltIn::Deinit() {
1380 // Destory color convert instance. This destroys thread and underlying GL resources.
1381 if (gl_layer_stitch_) {
1382 layer_stitch_task_.PerformTask(LayerStitchTaskCode::kCodeDestroyInstance, nullptr);
1383 }
1384
1385 histogram.stop();
1386 return HWCDisplay::Deinit();
1387 }
1388
OnTask(const LayerStitchTaskCode & task_code,SyncTask<LayerStitchTaskCode>::TaskContext * task_context)1389 void HWCDisplayBuiltIn::OnTask(const LayerStitchTaskCode &task_code,
1390 SyncTask<LayerStitchTaskCode>::TaskContext *task_context) {
1391 switch (task_code) {
1392 case LayerStitchTaskCode::kCodeGetInstance: {
1393 gl_layer_stitch_ = GLLayerStitch::GetInstance(false /* Non-secure */);
1394 }
1395 break;
1396 case LayerStitchTaskCode::kCodeStitch: {
1397 DTRACE_SCOPED();
1398 LayerStitchContext* ctx = reinterpret_cast<LayerStitchContext*>(task_context);
1399 gl_layer_stitch_->Blit(ctx->src_hnd, ctx->dst_hnd, ctx->src_rect, ctx->dst_rect,
1400 ctx->scissor_rect, ctx->src_acquire_fence,
1401 ctx->dst_acquire_fence, &(ctx->release_fence));
1402 }
1403 break;
1404 case LayerStitchTaskCode::kCodeDestroyInstance: {
1405 if (gl_layer_stitch_) {
1406 GLLayerStitch::Destroy(gl_layer_stitch_);
1407 }
1408 }
1409 break;
1410 }
1411 }
1412
InitLayerStitch()1413 bool HWCDisplayBuiltIn::InitLayerStitch() {
1414 if (!is_primary_) {
1415 // Disable on all non-primary builtins.
1416 DLOGI("Non-primary builtin.");
1417 disable_layer_stitch_ = true;
1418 return true;
1419 }
1420
1421 // Disable by default.
1422 int value = 1;
1423 Debug::Get()->GetProperty(DISABLE_LAYER_STITCH, &value);
1424 disable_layer_stitch_ = (value == 1);
1425
1426 if (disable_layer_stitch_) {
1427 DLOGI("Layer Stitch Disabled !!!");
1428 return true;
1429 }
1430
1431 // Initialize stitch context. This will be non-secure.
1432 layer_stitch_task_.PerformTask(LayerStitchTaskCode::kCodeGetInstance, nullptr);
1433 if (gl_layer_stitch_ == nullptr) {
1434 DLOGE("Failed to get LayerStitch Instance");
1435 return false;
1436 }
1437
1438 if (!AllocateStitchBuffer()) {
1439 return true;
1440 }
1441
1442 stitch_target_ = new HWCLayer(id_, static_cast<HWCBufferAllocator *>(buffer_allocator_));
1443
1444 // Populate buffer params and pvt handle.
1445 InitStitchTarget();
1446
1447 DLOGI("Created LayerStitch instance: %p", gl_layer_stitch_);
1448
1449 return true;
1450 }
1451
AllocateStitchBuffer()1452 bool HWCDisplayBuiltIn::AllocateStitchBuffer() {
1453 // Buffer dimensions: FB width * (1.5 * height)
1454
1455 DisplayError error = display_intf_->GetFrameBufferConfig(&fb_config_);
1456 if (error != kErrorNone) {
1457 DLOGE("Get frame buffer config failed. Error = %d", error);
1458 return false;
1459 }
1460
1461 BufferConfig &config = buffer_info_.buffer_config;
1462 config.width = fb_config_.x_pixels;
1463 config.height = fb_config_.y_pixels * kBufferHeightFactor;
1464
1465 // By default UBWC is enabled and below property is global enable/disable for all
1466 // buffers allocated through gralloc , including framebuffer targets.
1467 int ubwc_disabled = 0;
1468 HWCDebugHandler::Get()->GetProperty(DISABLE_UBWC_PROP, &ubwc_disabled);
1469 config.format = ubwc_disabled ? kFormatRGBA8888 : kFormatRGBA8888Ubwc;
1470
1471 config.gfx_client = true;
1472
1473 // Populate default params.
1474 config.secure = false;
1475 config.cache = false;
1476 config.secure_camera = false;
1477
1478 error = buffer_allocator_->AllocateBuffer(&buffer_info_);
1479
1480 if (error != kErrorNone) {
1481 DLOGE("Failed to allocate buffer. Error: %d", error);
1482 return false;
1483 }
1484
1485 return true;
1486 }
1487
InitStitchTarget()1488 void HWCDisplayBuiltIn::InitStitchTarget() {
1489 LayerBuffer buffer = {};
1490 buffer.planes[0].fd = buffer_info_.alloc_buffer_info.fd;
1491 buffer.planes[0].offset = 0;
1492 buffer.planes[0].stride = buffer_info_.alloc_buffer_info.stride;
1493 buffer.size = buffer_info_.alloc_buffer_info.size;
1494 buffer.handle_id = buffer_info_.alloc_buffer_info.id;
1495 buffer.width = buffer_info_.alloc_buffer_info.aligned_width;
1496 buffer.height = buffer_info_.alloc_buffer_info.aligned_height;
1497 buffer.unaligned_width = fb_config_.x_pixels;
1498 buffer.unaligned_height = fb_config_.y_pixels * kBufferHeightFactor;
1499 buffer.format = buffer_info_.alloc_buffer_info.format;
1500
1501 Layer *sdm_stitch_target = stitch_target_->GetSDMLayer();
1502 sdm_stitch_target->composition = kCompositionStitchTarget;
1503 sdm_stitch_target->input_buffer = buffer;
1504 sdm_stitch_target->input_buffer.buffer_id = reinterpret_cast<uint64_t>(buffer_info_.private_data);
1505 }
1506
AppendStitchLayer()1507 void HWCDisplayBuiltIn::AppendStitchLayer() {
1508 if (disable_layer_stitch_) {
1509 return;
1510 }
1511
1512 // Append stitch target buffer to layer stack.
1513 Layer *sdm_stitch_target = stitch_target_->GetSDMLayer();
1514 sdm_stitch_target->composition = kCompositionStitchTarget;
1515 sdm_stitch_target->dst_rect = {0, 0, FLOAT(fb_config_.x_pixels), FLOAT(fb_config_.y_pixels)};
1516 layer_stack_.layers.push_back(sdm_stitch_target);
1517 }
1518
HistogramEvent(int fd,uint32_t blob_id)1519 DisplayError HWCDisplayBuiltIn::HistogramEvent(int fd, uint32_t blob_id) {
1520 histogram.notify_histogram_event(fd, blob_id);
1521 return kErrorNone;
1522 }
1523
PostInit()1524 int HWCDisplayBuiltIn::PostInit() {
1525 auto status = InitLayerStitch();
1526 if (!status) {
1527 DLOGW("Failed to initialize Layer Stitch context");
1528 // Disable layer stitch.
1529 disable_layer_stitch_ = true;
1530 }
1531
1532 return 0;
1533 }
1534
HasReadBackBufferSupport()1535 bool HWCDisplayBuiltIn::HasReadBackBufferSupport() {
1536 DisplayConfigFixedInfo fixed_info = {};
1537 display_intf_->GetConfig(&fixed_info);
1538
1539 return fixed_info.readback_supported;
1540 }
1541
ApplyHbmLocked()1542 HWC2::Error HWCDisplayBuiltIn::ApplyHbmLocked() {
1543 if (!mHasHbmNode)
1544 return HWC2::Error::Unsupported;
1545
1546 HbmState state = HbmState::OFF;
1547 for (auto req : mHbmSates) {
1548 if (req == HbmState::SUNLIGHT) {
1549 state = HbmState::SUNLIGHT;
1550 break;
1551 } else if (req == HbmState::HDR) {
1552 state = HbmState::HDR;
1553 }
1554 }
1555
1556 if (state == mCurHbmState)
1557 return HWC2::Error::None;
1558
1559 std::string action = std::to_string(static_cast<int>(state));
1560 if (!android::base::WriteStringToFile(action, kHighBrightnessModeNode)) {
1561 DLOGE("Failed to write hbm node = %s, error = %s ", kHighBrightnessModeNode, strerror(errno));
1562 } else {
1563 DLOGI("write %s to HBM sysfs file succeeded", action.c_str());
1564 }
1565
1566 mCurHbmState = state;
1567
1568 return HWC2::Error::None;
1569 }
1570
IsHbmSupported()1571 bool HWCDisplayBuiltIn::IsHbmSupported() {
1572 if (!mHasHbmNode)
1573 return false;
1574
1575 bool is_hbm_supported = false;
1576 std::string buffer;
1577 if (!android::base::ReadFileToString(kHighBrightnessModeNode, &buffer)) {
1578 DLOGE("Failed to read hbm node = %s, error = %s ", kHighBrightnessModeNode, strerror(errno));
1579 } else if (buffer == "unsupported") {
1580 DLOGI("kernel driver does not support hbm");
1581 } else {
1582 is_hbm_supported = true;
1583 }
1584
1585 return is_hbm_supported;
1586 }
1587
SetHbm(HbmState state,HbmClient client)1588 HWC2::Error HWCDisplayBuiltIn::SetHbm(HbmState state, HbmClient client) {
1589 auto status = HWC2::Error::None;
1590 if (client >= CLIENT_MAX)
1591 return HWC2::Error::BadParameter;
1592
1593 std::unique_lock<decltype(hbm_mutex)> lk(hbm_mutex);
1594
1595 /* save and apply the request state */
1596 if (mHbmSates[client] != state) {
1597 mHbmSates[client] = state;
1598
1599 status = ApplyHbmLocked();
1600 if (INT32(status) != HWC2_ERROR_NONE)
1601 DLOGE("Failed to apply hbm node, error = %d", status);
1602 }
1603
1604 return status;
1605 }
1606
GetHbm()1607 HbmState HWCDisplayBuiltIn::GetHbm() {
1608 return mCurHbmState;
1609 }
1610
1611 } // namespace sdm
1612