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