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