Home | History | Annotate | Download | only in hwc
      1 /*
      2 * Copyright (c) 2014 - 2017, 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 <gr.h>
     38 #include "hwc_display_primary.h"
     39 #include "hwc_debugger.h"
     40 
     41 #define __CLASS__ "HWCDisplayPrimary"
     42 
     43 namespace sdm {
     44 
     45 int HWCDisplayPrimary::Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
     46                               hwc_procs_t const **hwc_procs, qService::QService *qservice,
     47                               HWCDisplay **hwc_display) {
     48   int status = 0;
     49   uint32_t primary_width = 0;
     50   uint32_t primary_height = 0;
     51 
     52   HWCDisplay *hwc_display_primary = new HWCDisplayPrimary(core_intf, buffer_allocator,
     53                                                           hwc_procs, qservice);
     54   status = hwc_display_primary->Init();
     55   if (status) {
     56     delete hwc_display_primary;
     57     return status;
     58   }
     59 
     60   hwc_display_primary->GetMixerResolution(&primary_width, &primary_height);
     61   int width = 0, height = 0;
     62   HWCDebugHandler::Get()->GetProperty("sdm.fb_size_width", &width);
     63   HWCDebugHandler::Get()->GetProperty("sdm.fb_size_height", &height);
     64   if (width > 0 && height > 0) {
     65     primary_width = UINT32(width);
     66     primary_height = UINT32(height);
     67   }
     68 
     69   status = hwc_display_primary->SetFrameBufferResolution(primary_width, primary_height);
     70   if (status) {
     71     Destroy(hwc_display_primary);
     72     return status;
     73   }
     74 
     75   *hwc_display = hwc_display_primary;
     76 
     77   return status;
     78 }
     79 
     80 void HWCDisplayPrimary::Destroy(HWCDisplay *hwc_display) {
     81   hwc_display->Deinit();
     82   delete hwc_display;
     83 }
     84 
     85 HWCDisplayPrimary::HWCDisplayPrimary(CoreInterface *core_intf,
     86                                      BufferAllocator *buffer_allocator,
     87                                      hwc_procs_t const **hwc_procs,
     88                                      qService::QService *qservice)
     89   : HWCDisplay(core_intf, hwc_procs, kPrimary, HWC_DISPLAY_PRIMARY, true, qservice,
     90                DISPLAY_CLASS_PRIMARY), buffer_allocator_(buffer_allocator) {
     91 }
     92 
     93 int HWCDisplayPrimary::Init() {
     94   cpu_hint_.Init(static_cast<HWCDebugHandler*>(HWCDebugHandler::Get()));
     95 
     96   use_metadata_refresh_rate_ = true;
     97   int disable_metadata_dynfps = 0;
     98   HWCDebugHandler::Get()->GetProperty("persist.metadata_dynfps.disable", &disable_metadata_dynfps);
     99   if (disable_metadata_dynfps) {
    100     use_metadata_refresh_rate_ = false;
    101   }
    102 
    103   int status = HWCDisplay::Init();
    104   if (status) {
    105     return status;
    106   }
    107   color_mode_ = new HWCColorMode(display_intf_);
    108   color_mode_->Init();
    109 
    110   return status;
    111 }
    112 
    113 int HWCDisplayPrimary::Deinit() {
    114   color_mode_->DeInit();
    115   delete color_mode_;
    116   color_mode_ = NULL;
    117 
    118   return HWCDisplay::Deinit();
    119 }
    120 
    121 
    122 void HWCDisplayPrimary::ProcessBootAnimCompleted(hwc_display_contents_1_t *list) {
    123   uint32_t numBootUpLayers = 0;
    124 
    125   numBootUpLayers = static_cast<uint32_t>(Debug::GetBootAnimLayerCount());
    126 
    127   if (numBootUpLayers == 0) {
    128     numBootUpLayers = 2;
    129   }
    130   /* All other checks namely "init.svc.bootanim" or
    131   * HWC_GEOMETRY_CHANGED fail in correctly identifying the
    132   * exact bootup transition to homescreen
    133   */
    134   char cryptoState[PROPERTY_VALUE_MAX];
    135   char voldDecryptState[PROPERTY_VALUE_MAX];
    136   bool isEncrypted = false;
    137   bool main_class_services_started = false;
    138   if (property_get("ro.crypto.state", cryptoState, "unencrypted")) {
    139     if (!strcmp(cryptoState, "encrypted")) {
    140       isEncrypted = true;
    141       if (property_get("vold.decrypt", voldDecryptState, "") &&
    142             !strcmp(voldDecryptState, "trigger_restart_framework"))
    143         main_class_services_started = true;
    144     }
    145   }
    146   if ((!isEncrypted ||(isEncrypted && main_class_services_started)) &&
    147     (list->numHwLayers > numBootUpLayers)) {
    148     boot_animation_completed_ = true;
    149     // Applying default mode after bootanimation is finished And
    150     // If Data is Encrypted, it is ready for access.
    151     if (display_intf_)
    152       display_intf_->ApplyDefaultDisplayMode();
    153   }
    154 }
    155 
    156 int HWCDisplayPrimary::Prepare(hwc_display_contents_1_t *content_list) {
    157   int status = 0;
    158   DisplayError error = kErrorNone;
    159 
    160   if (!boot_animation_completed_)
    161     ProcessBootAnimCompleted(content_list);
    162 
    163   if (display_paused_) {
    164     MarkLayersForGPUBypass(content_list);
    165     return status;
    166   }
    167 
    168   status = AllocateLayerStack(content_list);
    169   if (status) {
    170     return status;
    171   }
    172 
    173   status = PrePrepareLayerStack(content_list);
    174   if (status) {
    175     return status;
    176   }
    177 
    178   bool pending_output_dump = dump_frame_count_ && dump_output_to_file_;
    179 
    180   if (frame_capture_buffer_queued_ || pending_output_dump) {
    181     // RHS values were set in FrameCaptureAsync() called from a binder thread. They are picked up
    182     // here in a subsequent draw round.
    183     layer_stack_.output_buffer = &output_buffer_;
    184     layer_stack_.flags.post_processed_output = post_processed_output_;
    185   }
    186 
    187   uint32_t num_updating_layers = GetUpdatingLayersCount(UINT32(content_list->numHwLayers - 1));
    188   bool one_updating_layer = (num_updating_layers == 1);
    189 
    190   if (num_updating_layers != 0) {
    191     ToggleCPUHint(one_updating_layer);
    192   }
    193 
    194   uint32_t refresh_rate = GetOptimalRefreshRate(one_updating_layer);
    195   bool final_rate = force_refresh_rate_ ? true : false;
    196   error = display_intf_->SetRefreshRate(refresh_rate, final_rate);
    197   if (error == kErrorNone) {
    198     // On success, set current refresh rate to new refresh rate
    199     current_refresh_rate_ = refresh_rate;
    200   }
    201 
    202   if (content_list->numHwLayers <= 1) {
    203     flush_ = true;
    204   }
    205 
    206   status = PrepareLayerStack(content_list);
    207   if (status) {
    208     return status;
    209   }
    210 
    211   return 0;
    212 }
    213 
    214 int HWCDisplayPrimary::Commit(hwc_display_contents_1_t *content_list) {
    215   int status = 0;
    216 
    217   DisplayConfigFixedInfo display_config;
    218   display_intf_->GetConfig(&display_config);
    219   if (content_list->numHwLayers <= 1 && display_config.is_cmdmode) {
    220     DLOGV("Skipping null commit on cmd mode panel");
    221     flush_ = false;
    222     return 0;
    223   }
    224 
    225   if (display_paused_) {
    226     if (content_list->outbufAcquireFenceFd >= 0) {
    227       // If we do not handle the frame set retireFenceFd to outbufAcquireFenceFd,
    228       // which will make sure the framework waits on it and closes it.
    229       content_list->retireFenceFd = dup(content_list->outbufAcquireFenceFd);
    230       close(content_list->outbufAcquireFenceFd);
    231       content_list->outbufAcquireFenceFd = -1;
    232     }
    233 
    234     DisplayError error = display_intf_->Flush();
    235     if (error != kErrorNone) {
    236       DLOGE("Flush failed. Error = %d", error);
    237     }
    238     return status;
    239   }
    240 
    241   status = HWCDisplay::CommitLayerStack(content_list);
    242   if (status) {
    243     return status;
    244   }
    245 
    246   HandleFrameOutput();
    247 
    248   status = HWCDisplay::PostCommitLayerStack(content_list);
    249   if (status) {
    250     return status;
    251   }
    252 
    253   return 0;
    254 }
    255 
    256 int HWCDisplayPrimary::Perform(uint32_t operation, ...) {
    257   va_list args;
    258   va_start(args, operation);
    259   int val = va_arg(args, int32_t);
    260   va_end(args);
    261   switch (operation) {
    262     case SET_METADATA_DYN_REFRESH_RATE:
    263       SetMetaDataRefreshRateFlag(val);
    264       break;
    265     case SET_BINDER_DYN_REFRESH_RATE:
    266       ForceRefreshRate(UINT32(val));
    267       break;
    268     case SET_DISPLAY_MODE:
    269       SetDisplayMode(UINT32(val));
    270       break;
    271     case SET_QDCM_SOLID_FILL_INFO:
    272       SetQDCMSolidFillInfo(true, UINT32(val));
    273       break;
    274     case UNSET_QDCM_SOLID_FILL_INFO:
    275       SetQDCMSolidFillInfo(false, UINT32(val));
    276       break;
    277     default:
    278       DLOGW("Invalid operation %d", operation);
    279       return -EINVAL;
    280   }
    281 
    282   return 0;
    283 }
    284 
    285 DisplayError HWCDisplayPrimary::SetDisplayMode(uint32_t mode) {
    286   DisplayError error = kErrorNone;
    287 
    288   if (display_intf_) {
    289     error = display_intf_->SetDisplayMode(mode);
    290   }
    291 
    292   return error;
    293 }
    294 
    295 void HWCDisplayPrimary::SetMetaDataRefreshRateFlag(bool enable) {
    296   int disable_metadata_dynfps = 0;
    297 
    298   HWCDebugHandler::Get()->GetProperty("persist.metadata_dynfps.disable", &disable_metadata_dynfps);
    299   if (disable_metadata_dynfps) {
    300     return;
    301   }
    302   use_metadata_refresh_rate_ = enable;
    303 }
    304 
    305 void HWCDisplayPrimary::SetQDCMSolidFillInfo(bool enable, uint32_t color) {
    306   solid_fill_enable_ = enable;
    307   solid_fill_color_  = color;
    308 }
    309 
    310 void HWCDisplayPrimary::ToggleCPUHint(bool set) {
    311   if (set) {
    312     cpu_hint_.Set();
    313   } else {
    314     cpu_hint_.Reset();
    315   }
    316 }
    317 
    318 void HWCDisplayPrimary::SetSecureDisplay(bool secure_display_active, bool force_flush) {
    319   if (secure_display_active_ != secure_display_active) {
    320     // Skip Prepare and call Flush for null commit
    321     DLOGI("SecureDisplay state changed from %d to %d Needs Flush!!", secure_display_active_,
    322            secure_display_active);
    323     secure_display_active_ = secure_display_active;
    324     skip_prepare_cnt = 1;
    325 
    326     // Issue two null commits for command mode panels when external displays are connected.
    327     // Two null commits are required to handle non secure to secure transitions at 30fps.
    328     // TODO(user): Need two null commits on video mode also to handle transition cases of
    329     // primary at higher fps (ex60) and external at lower fps.
    330 
    331     // Avoid flush for command mode panels when no external displays are connected.
    332     // This is to avoid flicker/blink on primary during transitions.
    333     DisplayConfigFixedInfo display_config;
    334     display_intf_->GetConfig(&display_config);
    335     if (display_config.is_cmdmode) {
    336       if (force_flush) {
    337         DLOGI("Issue two null commits for command mode panels");
    338         skip_prepare_cnt = 2;
    339       } else {
    340         DLOGI("Avoid flush for command mode panel when no external displays are connected");
    341         skip_prepare_cnt = 0;
    342       }
    343     }
    344   }
    345 }
    346 
    347 void HWCDisplayPrimary::ForceRefreshRate(uint32_t refresh_rate) {
    348   if ((refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) ||
    349        force_refresh_rate_ == refresh_rate) {
    350     // Cannot honor force refresh rate, as its beyond the range or new request is same
    351     return;
    352   }
    353 
    354   const hwc_procs_t *hwc_procs = *hwc_procs_;
    355   force_refresh_rate_ = refresh_rate;
    356 
    357   hwc_procs->invalidate(hwc_procs);
    358 
    359   return;
    360 }
    361 
    362 uint32_t HWCDisplayPrimary::GetOptimalRefreshRate(bool one_updating_layer) {
    363   if (force_refresh_rate_) {
    364     return force_refresh_rate_;
    365   } else if (use_metadata_refresh_rate_ && one_updating_layer && metadata_refresh_rate_) {
    366     return metadata_refresh_rate_;
    367   }
    368 
    369   return max_refresh_rate_;
    370 }
    371 
    372 DisplayError HWCDisplayPrimary::Refresh() {
    373   const hwc_procs_t *hwc_procs = *hwc_procs_;
    374   DisplayError error = kErrorNone;
    375 
    376   if (!hwc_procs) {
    377     return kErrorParameters;
    378   }
    379 
    380   hwc_procs->invalidate(hwc_procs);
    381 
    382   return error;
    383 }
    384 
    385 void HWCDisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
    386   display_intf_->SetIdleTimeoutMs(timeout_ms);
    387 }
    388 
    389 static void SetLayerBuffer(const BufferInfo& output_buffer_info, LayerBuffer *output_buffer) {
    390   const BufferConfig& buffer_config = output_buffer_info.buffer_config;
    391   const AllocatedBufferInfo &alloc_buffer_info = output_buffer_info.alloc_buffer_info;
    392 
    393   output_buffer->width = alloc_buffer_info.aligned_width;
    394   output_buffer->height = alloc_buffer_info.aligned_height;
    395   output_buffer->unaligned_width = buffer_config.width;
    396   output_buffer->unaligned_height = buffer_config.height;
    397   output_buffer->format = buffer_config.format;
    398   output_buffer->planes[0].fd = alloc_buffer_info.fd;
    399   output_buffer->planes[0].stride = alloc_buffer_info.stride;
    400 }
    401 
    402 void HWCDisplayPrimary::HandleFrameOutput() {
    403   if (frame_capture_buffer_queued_) {
    404     HandleFrameCapture();
    405   } else if (dump_output_to_file_) {
    406     HandleFrameDump();
    407   }
    408 }
    409 
    410 void HWCDisplayPrimary::HandleFrameCapture() {
    411   if (output_buffer_.release_fence_fd >= 0) {
    412     frame_capture_status_ = sync_wait(output_buffer_.release_fence_fd, 1000);
    413     ::close(output_buffer_.release_fence_fd);
    414     output_buffer_.release_fence_fd = -1;
    415   }
    416 
    417   frame_capture_buffer_queued_ = false;
    418   post_processed_output_ = false;
    419   output_buffer_ = {};
    420 }
    421 
    422 void HWCDisplayPrimary::HandleFrameDump() {
    423   if (dump_frame_count_ && output_buffer_.release_fence_fd >= 0) {
    424     int ret = sync_wait(output_buffer_.release_fence_fd, 1000);
    425     ::close(output_buffer_.release_fence_fd);
    426     output_buffer_.release_fence_fd = -1;
    427     if (ret < 0) {
    428       DLOGE("sync_wait error errno = %d, desc = %s", errno,  strerror(errno));
    429     } else {
    430       DumpOutputBuffer(output_buffer_info_, output_buffer_base_, layer_stack_.retire_fence_fd);
    431     }
    432   }
    433 
    434   if (0 == dump_frame_count_) {
    435     dump_output_to_file_ = false;
    436     // Unmap and Free buffer
    437     if (munmap(output_buffer_base_, output_buffer_info_.alloc_buffer_info.size) != 0) {
    438       DLOGE("unmap failed with err %d", errno);
    439     }
    440     if (buffer_allocator_->FreeBuffer(&output_buffer_info_) != 0) {
    441       DLOGE("FreeBuffer failed");
    442     }
    443 
    444     post_processed_output_ = false;
    445     output_buffer_ = {};
    446     output_buffer_info_ = {};
    447     output_buffer_base_ = nullptr;
    448   }
    449 }
    450 
    451 void HWCDisplayPrimary::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
    452   HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
    453   dump_output_to_file_ = bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP);
    454   DLOGI("output_layer_dump_enable %d", dump_output_to_file_);
    455 
    456   if (!count || !dump_output_to_file_) {
    457     return;
    458   }
    459 
    460   // Allocate and map output buffer
    461   output_buffer_info_ = {};
    462   // Since we dump DSPP output use Panel resolution.
    463   GetPanelResolution(&output_buffer_info_.buffer_config.width,
    464                      &output_buffer_info_.buffer_config.height);
    465   output_buffer_info_.buffer_config.format = kFormatRGB888;
    466   output_buffer_info_.buffer_config.buffer_count = 1;
    467   if (buffer_allocator_->AllocateBuffer(&output_buffer_info_) != 0) {
    468     DLOGE("Buffer allocation failed");
    469     output_buffer_info_ = {};
    470     return;
    471   }
    472 
    473   void *buffer = mmap(NULL, output_buffer_info_.alloc_buffer_info.size,
    474                       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   DisablePartialUpdateOneFrame();
    487 }
    488 
    489 int HWCDisplayPrimary::FrameCaptureAsync(const BufferInfo& output_buffer_info,
    490                                          bool post_processed_output) {
    491   // Note: This function is called in context of a binder thread and a lock is already held
    492   if (output_buffer_info.alloc_buffer_info.fd < 0) {
    493     DLOGE("Invalid fd %d", output_buffer_info.alloc_buffer_info.fd);
    494     return -1;
    495   }
    496 
    497   auto panel_width = 0u;
    498   auto panel_height = 0u;
    499   auto fb_width = 0u;
    500   auto fb_height = 0u;
    501 
    502   GetPanelResolution(&panel_width, &panel_height);
    503   GetFrameBufferResolution(&fb_width, &fb_height);
    504 
    505   if (post_processed_output && (output_buffer_info.buffer_config.width < panel_width ||
    506                                 output_buffer_info.buffer_config.height < panel_height)) {
    507     DLOGE("Buffer dimensions should not be less than panel resolution");
    508     return -1;
    509   } else if (!post_processed_output && (output_buffer_info.buffer_config.width < fb_width ||
    510                                         output_buffer_info.buffer_config.height < fb_height)) {
    511     DLOGE("Buffer dimensions should not be less than FB resolution");
    512     return -1;
    513   }
    514 
    515   SetLayerBuffer(output_buffer_info, &output_buffer_);
    516   post_processed_output_ = post_processed_output;
    517   frame_capture_buffer_queued_ = true;
    518   // Status is only cleared on a new call to dump and remains valid otherwise
    519   frame_capture_status_ = -EAGAIN;
    520   DisablePartialUpdateOneFrame();
    521 
    522   return 0;
    523 }
    524 
    525 DisplayError HWCDisplayPrimary::SetDetailEnhancerConfig(
    526                                     const DisplayDetailEnhancerData &de_data) {
    527   DisplayError error = kErrorNotSupported;
    528   if (display_intf_) {
    529     error = display_intf_->SetDetailEnhancerData(de_data);
    530   }
    531   return error;
    532 }
    533 
    534 DisplayError HWCDisplayPrimary::ControlPartialUpdate(bool enable, uint32_t *pending) {
    535   DisplayError error = kErrorNone;
    536 
    537   if (display_intf_) {
    538     error = display_intf_->ControlPartialUpdate(enable, pending);
    539   }
    540 
    541   return error;
    542 }
    543 
    544 DisplayError HWCDisplayPrimary::DisablePartialUpdateOneFrame() {
    545   DisplayError error = kErrorNone;
    546 
    547   if (display_intf_) {
    548     error = display_intf_->DisablePartialUpdateOneFrame();
    549   }
    550 
    551   return error;
    552 }
    553 
    554 DisplayError HWCDisplayPrimary::SetMixerResolution(uint32_t width, uint32_t height) {
    555   return display_intf_->SetMixerResolution(width, height);
    556 }
    557 
    558 DisplayError HWCDisplayPrimary::GetMixerResolution(uint32_t *width, uint32_t *height) {
    559   return display_intf_->GetMixerResolution(width, height);
    560 }
    561 
    562 }  // namespace sdm
    563 
    564