blob: 517959e56c99734e2669a2c79ba67d2cc320b962 [file] [log] [blame]
Naseer Ahmedb92e73f2016-03-12 02:03:48 -05001/*
2* Copyright (c) 2014 - 2016, 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 <stdarg.h>
35#include <sys/mman.h>
36
Arun Kumar K.R29cd6582016-05-10 19:12:45 -070037#include <map>
38#include <string>
39#include <vector>
40
Naseer Ahmedb92e73f2016-03-12 02:03:48 -050041#include "hwc_display_primary.h"
42#include "hwc_debugger.h"
43
44#define __CLASS__ "HWCDisplayPrimary"
45
46namespace sdm {
47
48int HWCDisplayPrimary::Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
49 HWCCallbacks *callbacks, qService::QService *qservice,
50 HWCDisplay **hwc_display) {
51 int status = 0;
52 uint32_t primary_width = 0;
53 uint32_t primary_height = 0;
54
55 HWCDisplay *hwc_display_primary =
56 new HWCDisplayPrimary(core_intf, buffer_allocator, callbacks, qservice);
57 status = hwc_display_primary->Init();
58 if (status) {
59 delete hwc_display_primary;
60 return status;
61 }
62
63 hwc_display_primary->GetPanelResolution(&primary_width, &primary_height);
64 int width = 0, height = 0;
65 HWCDebugHandler::Get()->GetProperty("sdm.fb_size_width", &width);
66 HWCDebugHandler::Get()->GetProperty("sdm.fb_size_height", &height);
67 if (width > 0 && height > 0) {
68 primary_width = UINT32(width);
69 primary_height = UINT32(height);
70 }
71
72 status = hwc_display_primary->SetFrameBufferResolution(primary_width, primary_height);
73 if (status) {
74 Destroy(hwc_display_primary);
75 return status;
76 }
77
78 *hwc_display = hwc_display_primary;
79
80 return status;
81}
82
83void HWCDisplayPrimary::Destroy(HWCDisplay *hwc_display) {
84 hwc_display->Deinit();
85 delete hwc_display;
86}
87
88HWCDisplayPrimary::HWCDisplayPrimary(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
89 HWCCallbacks *callbacks, qService::QService *qservice)
90 : HWCDisplay(core_intf, callbacks, kPrimary, HWC_DISPLAY_PRIMARY, true, qservice,
91 DISPLAY_CLASS_PRIMARY),
92 buffer_allocator_(buffer_allocator),
93 cpu_hint_(NULL) {
94}
95
96int HWCDisplayPrimary::Init() {
97 cpu_hint_ = new CPUHint();
98 if (cpu_hint_->Init(static_cast<HWCDebugHandler *>(HWCDebugHandler::Get())) != kErrorNone) {
99 delete cpu_hint_;
100 cpu_hint_ = NULL;
101 }
102
103 use_metadata_refresh_rate_ = true;
104 int disable_metadata_dynfps = 0;
105 HWCDebugHandler::Get()->GetProperty("persist.metadata_dynfps.disable", &disable_metadata_dynfps);
106 if (disable_metadata_dynfps) {
107 use_metadata_refresh_rate_ = false;
108 }
109
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700110 int status = HWCDisplay::Init();
111 if (status) {
112 return status;
113 }
114 color_mode_ = new HWCColorMode(display_intf_);
115
116 return INT(color_mode_->Init());
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500117}
118
119void HWCDisplayPrimary::ProcessBootAnimCompleted() {
120 uint32_t numBootUpLayers = 0;
121 // TODO(user): Remove this hack
122
123 numBootUpLayers = static_cast<uint32_t>(Debug::GetBootAnimLayerCount());
124
125 if (numBootUpLayers == 0) {
126 numBootUpLayers = 2;
127 }
128 /* All other checks namely "init.svc.bootanim" or
129 * HWC_GEOMETRY_CHANGED fail in correctly identifying the
130 * exact bootup transition to homescreen
131 */
132 char cryptoState[PROPERTY_VALUE_MAX];
133 char voldDecryptState[PROPERTY_VALUE_MAX];
134 bool isEncrypted = false;
135 bool main_class_services_started = false;
136 if (property_get("ro.crypto.state", cryptoState, "unencrypted")) {
137 if (!strcmp(cryptoState, "encrypted")) {
138 isEncrypted = true;
139 if (property_get("vold.decrypt", voldDecryptState, "") &&
140 !strcmp(voldDecryptState, "trigger_restart_framework"))
141 main_class_services_started = true;
142 }
143 }
144 if ((!isEncrypted || (isEncrypted && main_class_services_started)) &&
145 (layer_set_.size() > numBootUpLayers)) {
146 boot_animation_completed_ = true;
147 // Applying default mode after bootanimation is finished And
148 // If Data is Encrypted, it is ready for access.
149 if (display_intf_)
150 display_intf_->ApplyDefaultDisplayMode();
151 }
152}
153
154HWC2::Error HWCDisplayPrimary::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
155 auto status = HWC2::Error::None;
156 DisplayError error = kErrorNone;
157
158 if (!boot_animation_completed_)
159 ProcessBootAnimCompleted();
160
161 if (display_paused_) {
162 MarkLayersForGPUBypass();
163 return status;
164 }
165
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700166 if (color_tranform_failed_) {
167 // Must fall back to client composition
168 MarkLayersForClientComposition();
169 }
170
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500171 // Fill in the remaining blanks in the layers and add them to the SDM layerstack
172 BuildLayerStack();
173
174 bool pending_output_dump = dump_frame_count_ && dump_output_to_file_;
175
176 if (frame_capture_buffer_queued_ || pending_output_dump) {
177 // RHS values were set in FrameCaptureAsync() called from a binder thread. They are picked up
178 // here in a subsequent draw round.
179 layer_stack_.output_buffer = &output_buffer_;
180 layer_stack_.flags.post_processed_output = post_processed_output_;
181 }
182
183 bool one_updating_layer = SingleLayerUpdating();
184 ToggleCPUHint(one_updating_layer);
185
186 uint32_t refresh_rate = GetOptimalRefreshRate(one_updating_layer);
187 if (current_refresh_rate_ != refresh_rate) {
188 error = display_intf_->SetRefreshRate(refresh_rate);
189 }
190
191 if (error == kErrorNone) {
192 // On success, set current refresh rate to new refresh rate
193 current_refresh_rate_ = refresh_rate;
194 }
195
196 if (handle_idle_timeout_) {
197 handle_idle_timeout_ = false;
198 }
199
200 // TODO(user): Validate this
201 if (layer_set_.empty()) {
202 flush_ = true;
203 return status;
204 }
205
206 status = PrepareLayerStack(out_num_types, out_num_requests);
207 return status;
208}
209
210HWC2::Error HWCDisplayPrimary::Present(int32_t *out_retire_fence) {
211 auto status = HWC2::Error::None;
212 if (display_paused_) {
213 // TODO(user): From old HWC implementation
214 // If we do not handle the frame set retireFenceFd to outbufAcquireFenceFd
215 // Revisit this when validating display_paused
216 DisplayError error = display_intf_->Flush();
217 if (error != kErrorNone) {
218 DLOGE("Flush failed. Error = %d", error);
219 }
220 } else {
221 status = HWCDisplay::CommitLayerStack();
222 if (status == HWC2::Error::None) {
223 HandleFrameOutput();
224 status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
225 }
226 }
227 CloseAcquireFds();
228 return status;
229}
230
Arun Kumar K.R29cd6582016-05-10 19:12:45 -0700231HWC2::Error HWCDisplayPrimary::GetColorModes(uint32_t *out_num_modes,
232 int32_t /*android_color_mode_t*/ *out_modes) {
233 if (out_modes == nullptr) {
234 *out_num_modes = color_mode_->GetColorModeCount();
235 } else {
236 color_mode_->GetColorModes(out_num_modes, out_modes);
237 }
238
239 return HWC2::Error::None;
240}
241
242HWC2::Error HWCDisplayPrimary::SetColorMode(int32_t /*android_color_mode_t*/ mode) {
243 auto status = color_mode_->SetColorMode(mode);
244 if (status != HWC2::Error::None) {
245 DLOGE("failed for mode = %d", mode);
246 return status;
247 }
248
249 callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
250
251 return status;
252}
253
254HWC2::Error HWCDisplayPrimary::SetColorTransform(const float *matrix,
255 android_color_transform_t hint) {
256 if (!matrix) {
257 return HWC2::Error::BadParameter;
258 }
259
260 auto status = color_mode_->SetColorTransform(matrix, hint);
261 if (status != HWC2::Error::None) {
262 DLOGE("failed for hint = %d", hint);
263 color_tranform_failed_ = true;
264 return status;
265 }
266
267 callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
268 color_tranform_failed_ = false;
269
270 return status;
271}
272
Naseer Ahmedb92e73f2016-03-12 02:03:48 -0500273int HWCDisplayPrimary::Perform(uint32_t operation, ...) {
274 va_list args;
275 va_start(args, operation);
276 int val = va_arg(args, int32_t);
277 va_end(args);
278 switch (operation) {
279 case SET_METADATA_DYN_REFRESH_RATE:
280 SetMetaDataRefreshRateFlag(val);
281 break;
282 case SET_BINDER_DYN_REFRESH_RATE:
283 ForceRefreshRate(UINT32(val));
284 break;
285 case SET_DISPLAY_MODE:
286 SetDisplayMode(UINT32(val));
287 break;
288 case SET_QDCM_SOLID_FILL_INFO:
289 SetQDCMSolidFillInfo(true, UINT32(val));
290 break;
291 case UNSET_QDCM_SOLID_FILL_INFO:
292 SetQDCMSolidFillInfo(false, UINT32(val));
293 break;
294 default:
295 DLOGW("Invalid operation %d", operation);
296 return -EINVAL;
297 }
298
299 return 0;
300}
301
302DisplayError HWCDisplayPrimary::SetDisplayMode(uint32_t mode) {
303 DisplayError error = kErrorNone;
304
305 if (display_intf_) {
306 error = display_intf_->SetDisplayMode(mode);
307 }
308
309 return error;
310}
311
312void HWCDisplayPrimary::SetMetaDataRefreshRateFlag(bool enable) {
313 int disable_metadata_dynfps = 0;
314
315 HWCDebugHandler::Get()->GetProperty("persist.metadata_dynfps.disable", &disable_metadata_dynfps);
316 if (disable_metadata_dynfps) {
317 return;
318 }
319 use_metadata_refresh_rate_ = enable;
320}
321
322void HWCDisplayPrimary::SetQDCMSolidFillInfo(bool enable, uint32_t color) {
323 solid_fill_enable_ = enable;
324 solid_fill_color_ = color;
325}
326
327void HWCDisplayPrimary::ToggleCPUHint(bool set) {
328 if (!cpu_hint_) {
329 return;
330 }
331
332 if (set) {
333 cpu_hint_->Set();
334 } else {
335 cpu_hint_->Reset();
336 }
337}
338
339void HWCDisplayPrimary::SetSecureDisplay(bool secure_display_active) {
340 if (secure_display_active_ != secure_display_active) {
341 // Skip Prepare and call Flush for null commit
342 DLOGI("SecureDisplay state changed from %d to %d Needs Flush!!", secure_display_active_,
343 secure_display_active);
344 secure_display_active_ = secure_display_active;
345 skip_prepare_ = true;
346 }
347 return;
348}
349
350void HWCDisplayPrimary::ForceRefreshRate(uint32_t refresh_rate) {
351 if ((refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) ||
352 force_refresh_rate_ == refresh_rate) {
353 // Cannot honor force refresh rate, as its beyond the range or new request is same
354 return;
355 }
356
357 force_refresh_rate_ = refresh_rate;
358
359 callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
360
361 return;
362}
363
364uint32_t HWCDisplayPrimary::GetOptimalRefreshRate(bool one_updating_layer) {
365 if (force_refresh_rate_) {
366 return force_refresh_rate_;
367 } else if (handle_idle_timeout_) {
368 return min_refresh_rate_;
369 } else if (use_metadata_refresh_rate_ && one_updating_layer && metadata_refresh_rate_) {
370 return metadata_refresh_rate_;
371 }
372
373 return max_refresh_rate_;
374}
375
376DisplayError HWCDisplayPrimary::Refresh() {
377 DisplayError error = kErrorNone;
378
379 callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
380 handle_idle_timeout_ = true;
381
382 return error;
383}
384
385void HWCDisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
386 display_intf_->SetIdleTimeoutMs(timeout_ms);
387}
388
389static void SetLayerBuffer(const BufferInfo &output_buffer_info, LayerBuffer *output_buffer) {
390 output_buffer->width = output_buffer_info.buffer_config.width;
391 output_buffer->height = output_buffer_info.buffer_config.height;
392 output_buffer->format = output_buffer_info.buffer_config.format;
393 output_buffer->planes[0].fd = output_buffer_info.alloc_buffer_info.fd;
394 output_buffer->planes[0].stride = output_buffer_info.alloc_buffer_info.stride;
395}
396
397void HWCDisplayPrimary::HandleFrameOutput() {
398 if (frame_capture_buffer_queued_) {
399 HandleFrameCapture();
400 } else if (dump_output_to_file_) {
401 HandleFrameDump();
402 }
403}
404
405void HWCDisplayPrimary::HandleFrameCapture() {
406 if (output_buffer_.release_fence_fd >= 0) {
407 frame_capture_status_ = sync_wait(output_buffer_.release_fence_fd, 1000);
408 ::close(output_buffer_.release_fence_fd);
409 output_buffer_.release_fence_fd = -1;
410 }
411
412 frame_capture_buffer_queued_ = false;
413 post_processed_output_ = false;
414 output_buffer_ = {};
415
416 uint32_t pending = 0; // Just a temporary to satisfy the API
417 ControlPartialUpdate(true /* enable */, &pending);
418}
419
420void HWCDisplayPrimary::HandleFrameDump() {
421 if (dump_frame_count_ && output_buffer_.release_fence_fd >= 0) {
422 int ret = sync_wait(output_buffer_.release_fence_fd, 1000);
423 ::close(output_buffer_.release_fence_fd);
424 output_buffer_.release_fence_fd = -1;
425 if (ret < 0) {
426 DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
427 } else {
428 DumpOutputBuffer(output_buffer_info_, output_buffer_base_, layer_stack_.retire_fence_fd);
429 }
430 }
431
432 if (0 == dump_frame_count_) {
433 dump_output_to_file_ = false;
434 // Unmap and Free buffer
435 if (munmap(output_buffer_base_, output_buffer_info_.alloc_buffer_info.size) != 0) {
436 DLOGE("unmap failed with err %d", errno);
437 }
438 if (buffer_allocator_->FreeBuffer(&output_buffer_info_) != 0) {
439 DLOGE("FreeBuffer failed");
440 }
441
442 post_processed_output_ = false;
443 output_buffer_ = {};
444 output_buffer_info_ = {};
445 output_buffer_base_ = nullptr;
446
447 uint32_t pending = 0; // Just a temporary to satisfy the API
448 ControlPartialUpdate(true /* enable */, &pending);
449 }
450}
451
452void HWCDisplayPrimary::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
453 HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
454 dump_output_to_file_ = bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP);
455 DLOGI("output_layer_dump_enable %d", dump_output_to_file_);
456
457 if (!count || !dump_output_to_file_) {
458 return;
459 }
460
461 // Allocate and map output buffer
462 output_buffer_info_ = {};
463 // Since we dump DSPP output use Panel resolution.
464 GetPanelResolution(&output_buffer_info_.buffer_config.width,
465 &output_buffer_info_.buffer_config.height);
466 output_buffer_info_.buffer_config.format = kFormatRGB888;
467 output_buffer_info_.buffer_config.buffer_count = 1;
468 if (buffer_allocator_->AllocateBuffer(&output_buffer_info_) != 0) {
469 DLOGE("Buffer allocation failed");
470 output_buffer_info_ = {};
471 return;
472 }
473
474 void *buffer = mmap(NULL, output_buffer_info_.alloc_buffer_info.size, PROT_READ | PROT_WRITE,
475 MAP_SHARED, output_buffer_info_.alloc_buffer_info.fd, 0);
476
477 if (buffer == MAP_FAILED) {
478 DLOGE("mmap failed with err %d", errno);
479 buffer_allocator_->FreeBuffer(&output_buffer_info_);
480 output_buffer_info_ = {};
481 return;
482 }
483
484 output_buffer_base_ = buffer;
485 post_processed_output_ = true;
486 uint32_t pending = 0; // Just a temporary to satisfy the API
487 ControlPartialUpdate(false /* enable */, &pending);
488}
489
490int HWCDisplayPrimary::FrameCaptureAsync(const BufferInfo &output_buffer_info,
491 bool post_processed_output) {
492 // Note: This function is called in context of a binder thread and a lock is already held
493 if (output_buffer_info.alloc_buffer_info.fd < 0) {
494 DLOGE("Invalid fd %d", output_buffer_info.alloc_buffer_info.fd);
495 return -1;
496 }
497
498 auto panel_width = 0u;
499 auto panel_height = 0u;
500 auto fb_width = 0u;
501 auto fb_height = 0u;
502
503 GetPanelResolution(&panel_width, &panel_height);
504 GetFrameBufferResolution(&fb_width, &fb_height);
505
506 if (post_processed_output && (output_buffer_info_.buffer_config.width < panel_width ||
507 output_buffer_info_.buffer_config.height < panel_height)) {
508 DLOGE("Buffer dimensions should not be less than panel resolution");
509 return -1;
510 } else if (!post_processed_output && (output_buffer_info_.buffer_config.width < fb_width ||
511 output_buffer_info_.buffer_config.height < fb_height)) {
512 DLOGE("Buffer dimensions should not be less than FB resolution");
513 return -1;
514 }
515
516 SetLayerBuffer(output_buffer_info, &output_buffer_);
517 post_processed_output_ = post_processed_output;
518 frame_capture_buffer_queued_ = true;
519 // Status is only cleared on a new call to dump and remains valid otherwise
520 frame_capture_status_ = -EAGAIN;
521
522 uint32_t pending = 0; // Just a temporary to satisfy the API
523 ControlPartialUpdate(false /* enable */, &pending);
524
525 return 0;
526}
527
528} // namespace sdm