Home | History | Annotate | Download | only in core
      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 modification, are permitted
      5 * provided that the following conditions are met:
      6 *    * Redistributions of source code must retain the above copyright notice, this list of
      7 *      conditions and the following disclaimer.
      8 *    * Redistributions in binary form must reproduce the above copyright notice, this list of
      9 *      conditions and the following disclaimer in the documentation and/or other materials provided
     10 *      with the distribution.
     11 *    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
     12 *      endorse or promote products derived from this software without specific prior written
     13 *      permission.
     14 *
     15 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     17 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
     18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     20 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     21 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     22 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23 */
     24 
     25 #include <utils/constants.h>
     26 #include <utils/debug.h>
     27 #include <core/buffer_allocator.h>
     28 
     29 #include "comp_manager.h"
     30 #include "strategy.h"
     31 
     32 #define __CLASS__ "CompManager"
     33 
     34 namespace sdm {
     35 
     36 DisplayError CompManager::Init(const HWResourceInfo &hw_res_info,
     37                                ExtensionInterface *extension_intf,
     38                                BufferAllocator *buffer_allocator,
     39                                BufferSyncHandler *buffer_sync_handler,
     40                                SocketHandler *socket_handler) {
     41   SCOPE_LOCK(locker_);
     42 
     43   DisplayError error = kErrorNone;
     44 
     45   if (extension_intf) {
     46     error = extension_intf->CreateResourceExtn(hw_res_info, buffer_allocator, buffer_sync_handler,
     47                                                &resource_intf_);
     48     extension_intf->CreateDppsControlExtn(&dpps_ctrl_intf_, socket_handler);
     49   } else {
     50     error = ResourceDefault::CreateResourceDefault(hw_res_info, &resource_intf_);
     51   }
     52 
     53   if (error != kErrorNone) {
     54     if (extension_intf) {
     55       extension_intf->DestroyDppsControlExtn(dpps_ctrl_intf_);
     56     }
     57     return error;
     58   }
     59 
     60   hw_res_info_ = hw_res_info;
     61   buffer_allocator_ = buffer_allocator;
     62   extension_intf_ = extension_intf;
     63 
     64   return error;
     65 }
     66 
     67 DisplayError CompManager::Deinit() {
     68   SCOPE_LOCK(locker_);
     69 
     70   if (extension_intf_) {
     71     extension_intf_->DestroyResourceExtn(resource_intf_);
     72     extension_intf_->DestroyDppsControlExtn(dpps_ctrl_intf_);
     73   } else {
     74     ResourceDefault::DestroyResourceDefault(resource_intf_);
     75   }
     76 
     77   return kErrorNone;
     78 }
     79 
     80 DisplayError CompManager::RegisterDisplay(DisplayType type,
     81                                           const HWDisplayAttributes &display_attributes,
     82                                           const HWPanelInfo &hw_panel_info,
     83                                           const HWMixerAttributes &mixer_attributes,
     84                                           const DisplayConfigVariableInfo &fb_config,
     85                                           Handle *display_ctx) {
     86   SCOPE_LOCK(locker_);
     87 
     88   DisplayError error = kErrorNone;
     89 
     90   DisplayCompositionContext *display_comp_ctx = new DisplayCompositionContext();
     91   if (!display_comp_ctx) {
     92     return kErrorMemory;
     93   }
     94 
     95   Strategy *&strategy = display_comp_ctx->strategy;
     96   strategy = new Strategy(extension_intf_, buffer_allocator_, type, hw_res_info_, hw_panel_info,
     97                           mixer_attributes, display_attributes, fb_config);
     98   if (!strategy) {
     99     DLOGE("Unable to create strategy");
    100     delete display_comp_ctx;
    101     return kErrorMemory;
    102   }
    103 
    104   error = strategy->Init();
    105   if (error != kErrorNone) {
    106     delete strategy;
    107     delete display_comp_ctx;
    108     return error;
    109   }
    110 
    111   error = resource_intf_->RegisterDisplay(type, display_attributes, hw_panel_info, mixer_attributes,
    112                                           &display_comp_ctx->display_resource_ctx);
    113   if (error != kErrorNone) {
    114     strategy->Deinit();
    115     delete strategy;
    116     delete display_comp_ctx;
    117     display_comp_ctx = NULL;
    118     return error;
    119   }
    120 
    121   registered_displays_[type] = 1;
    122   display_comp_ctx->is_primary_panel = hw_panel_info.is_primary_panel;
    123   display_comp_ctx->display_type = type;
    124   *display_ctx = display_comp_ctx;
    125   // New non-primary display device has been added, so move the composition mode to safe mode until
    126   // resources for the added display is configured properly.
    127   if (!display_comp_ctx->is_primary_panel) {
    128     safe_mode_ = true;
    129     max_sde_ext_layers_ = UINT32(Debug::GetExtMaxlayers());
    130   }
    131 
    132   DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
    133            "display type %d", registered_displays_.to_ulong(), configured_displays_.to_ulong(),
    134            display_comp_ctx->display_type);
    135 
    136   return kErrorNone;
    137 }
    138 
    139 DisplayError CompManager::UnregisterDisplay(Handle display_ctx) {
    140   SCOPE_LOCK(locker_);
    141 
    142   DisplayCompositionContext *display_comp_ctx =
    143                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    144 
    145   if (!display_comp_ctx) {
    146     return kErrorParameters;
    147   }
    148 
    149   resource_intf_->UnregisterDisplay(display_comp_ctx->display_resource_ctx);
    150 
    151   Strategy *&strategy = display_comp_ctx->strategy;
    152   strategy->Deinit();
    153   delete strategy;
    154 
    155   registered_displays_[display_comp_ctx->display_type] = 0;
    156   configured_displays_[display_comp_ctx->display_type] = 0;
    157 
    158   if (display_comp_ctx->display_type == kHDMI) {
    159     max_layers_ = kMaxSDELayers;
    160   }
    161 
    162   DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
    163            "display type %d", registered_displays_.to_ulong(), configured_displays_.to_ulong(),
    164            display_comp_ctx->display_type);
    165 
    166   delete display_comp_ctx;
    167   display_comp_ctx = NULL;
    168   return kErrorNone;
    169 }
    170 
    171 DisplayError CompManager::ReconfigureDisplay(Handle comp_handle,
    172                                              const HWDisplayAttributes &display_attributes,
    173                                              const HWPanelInfo &hw_panel_info,
    174                                              const HWMixerAttributes &mixer_attributes,
    175                                              const DisplayConfigVariableInfo &fb_config) {
    176   SCOPE_LOCK(locker_);
    177 
    178   DisplayError error = kErrorNone;
    179   DisplayCompositionContext *display_comp_ctx =
    180                              reinterpret_cast<DisplayCompositionContext *>(comp_handle);
    181 
    182   error = resource_intf_->ReconfigureDisplay(display_comp_ctx->display_resource_ctx,
    183                                              display_attributes, hw_panel_info, mixer_attributes);
    184   if (error != kErrorNone) {
    185     return error;
    186   }
    187 
    188   if (display_comp_ctx->strategy) {
    189     error = display_comp_ctx->strategy->Reconfigure(hw_panel_info, display_attributes,
    190                                                     mixer_attributes, fb_config);
    191     if (error != kErrorNone) {
    192       DLOGE("Unable to Reconfigure strategy.");
    193       display_comp_ctx->strategy->Deinit();
    194       delete display_comp_ctx->strategy;
    195       display_comp_ctx->strategy = NULL;
    196       return error;
    197     }
    198   }
    199 
    200   // For HDMI S3D mode, set max_layers_ to 0 so that primary display would fall back
    201   // to GPU composition to release pipes for HDMI.
    202   if (display_comp_ctx->display_type == kHDMI) {
    203     if (hw_panel_info.s3d_mode != kS3DModeNone) {
    204       max_layers_ = 0;
    205     } else {
    206       max_layers_ = kMaxSDELayers;
    207     }
    208   }
    209 
    210   return error;
    211 }
    212 
    213 void CompManager::PrepareStrategyConstraints(Handle comp_handle, HWLayers *hw_layers) {
    214   DisplayCompositionContext *display_comp_ctx =
    215                              reinterpret_cast<DisplayCompositionContext *>(comp_handle);
    216   StrategyConstraints *constraints = &display_comp_ctx->constraints;
    217 
    218   constraints->safe_mode = safe_mode_;
    219   constraints->max_layers = max_layers_;
    220 
    221   // Limit 2 layer SDE Comp if its not a Primary Display.
    222   // Safe mode is the policy for External display on a low end device.
    223   if (!display_comp_ctx->is_primary_panel) {
    224     bool low_end_hw = ((hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe +
    225                         hw_res_info_.num_dma_pipe) <= kSafeModeThreshold);
    226     constraints->max_layers = max_sde_ext_layers_;
    227     constraints->safe_mode = (low_end_hw && !hw_res_info_.separate_rotator) ? true : safe_mode_;
    228   }
    229 
    230   // If a strategy fails after successfully allocating resources, then set safe mode
    231   if (display_comp_ctx->remaining_strategies != display_comp_ctx->max_strategies) {
    232     constraints->safe_mode = true;
    233   }
    234 
    235   // TODO(user): App layer count will change for hybrid composition
    236   uint32_t app_layer_count = UINT32(hw_layers->info.stack->layers.size()) - 1;
    237   if (display_comp_ctx->idle_fallback || display_comp_ctx->thermal_fallback_) {
    238     // Handle the idle timeout by falling back
    239     constraints->safe_mode = true;
    240   }
    241 
    242   // Avoid safe mode, if there is only one app layer.
    243   if (app_layer_count == 1) {
    244      constraints->safe_mode = false;
    245   }
    246 }
    247 
    248 void CompManager::PrePrepare(Handle display_ctx, HWLayers *hw_layers) {
    249   SCOPE_LOCK(locker_);
    250   DisplayCompositionContext *display_comp_ctx =
    251                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    252   display_comp_ctx->strategy->Start(&hw_layers->info, &display_comp_ctx->max_strategies,
    253                                     display_comp_ctx->pu_constraints);
    254   display_comp_ctx->remaining_strategies = display_comp_ctx->max_strategies;
    255 }
    256 
    257 DisplayError CompManager::Prepare(Handle display_ctx, HWLayers *hw_layers) {
    258   SCOPE_LOCK(locker_);
    259 
    260   DisplayCompositionContext *display_comp_ctx =
    261                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    262   Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
    263 
    264   DisplayError error = kErrorUndefined;
    265 
    266   PrepareStrategyConstraints(display_ctx, hw_layers);
    267 
    268   // Select a composition strategy, and try to allocate resources for it.
    269   resource_intf_->Start(display_resource_ctx);
    270 
    271   bool exit = false;
    272   uint32_t &count = display_comp_ctx->remaining_strategies;
    273   for (; !exit && count > 0; count--) {
    274     error = display_comp_ctx->strategy->GetNextStrategy(&display_comp_ctx->constraints);
    275     if (error != kErrorNone) {
    276       // Composition strategies exhausted. Resource Manager could not allocate resources even for
    277       // GPU composition. This will never happen.
    278       exit = true;
    279     }
    280 
    281     if (!exit) {
    282       error = resource_intf_->Prepare(display_resource_ctx, hw_layers);
    283       // Exit if successfully prepared resource, else try next strategy.
    284       exit = (error == kErrorNone);
    285     }
    286   }
    287 
    288   if (error != kErrorNone) {
    289     DLOGE("Composition strategies exhausted for display = %d", display_comp_ctx->display_type);
    290   }
    291 
    292   resource_intf_->Stop(display_resource_ctx);
    293 
    294   return error;
    295 }
    296 
    297 DisplayError CompManager::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
    298   SCOPE_LOCK(locker_);
    299   DisplayCompositionContext *display_comp_ctx =
    300                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    301   Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
    302 
    303   DisplayError error = kErrorNone;
    304   error = resource_intf_->PostPrepare(display_resource_ctx, hw_layers);
    305   if (error != kErrorNone) {
    306     return error;
    307   }
    308 
    309   display_comp_ctx->strategy->Stop();
    310 
    311   return kErrorNone;
    312 }
    313 
    314 DisplayError CompManager::Commit(Handle display_ctx, HWLayers *hw_layers) {
    315   SCOPE_LOCK(locker_);
    316 
    317   DisplayCompositionContext *display_comp_ctx =
    318                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    319 
    320   return resource_intf_->Commit(display_comp_ctx->display_resource_ctx, hw_layers);
    321 }
    322 
    323 DisplayError CompManager::ReConfigure(Handle display_ctx, HWLayers *hw_layers) {
    324   SCOPE_LOCK(locker_);
    325 
    326   DisplayCompositionContext *display_comp_ctx =
    327                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    328   Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
    329 
    330   DisplayError error = kErrorUndefined;
    331   resource_intf_->Start(display_resource_ctx);
    332   error = resource_intf_->Prepare(display_resource_ctx, hw_layers);
    333 
    334   if (error != kErrorNone) {
    335     DLOGE("Reconfigure failed for display = %d", display_comp_ctx->display_type);
    336   }
    337 
    338   resource_intf_->Stop(display_resource_ctx);
    339   if (error != kErrorNone) {
    340       error = resource_intf_->PostPrepare(display_resource_ctx, hw_layers);
    341   }
    342 
    343   return error;
    344 }
    345 
    346 DisplayError CompManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
    347   SCOPE_LOCK(locker_);
    348 
    349   DisplayError error = kErrorNone;
    350   DisplayCompositionContext *display_comp_ctx =
    351                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    352   configured_displays_[display_comp_ctx->display_type] = 1;
    353   if (configured_displays_ == registered_displays_) {
    354     safe_mode_ = false;
    355   }
    356 
    357   error = resource_intf_->PostCommit(display_comp_ctx->display_resource_ctx, hw_layers);
    358   if (error != kErrorNone) {
    359     return error;
    360   }
    361 
    362   display_comp_ctx->idle_fallback = false;
    363 
    364   DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
    365            "display type %d", registered_displays_, configured_displays_,
    366            display_comp_ctx->display_type);
    367 
    368   return kErrorNone;
    369 }
    370 
    371 void CompManager::Purge(Handle display_ctx) {
    372   SCOPE_LOCK(locker_);
    373 
    374   DisplayCompositionContext *display_comp_ctx =
    375                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    376 
    377   resource_intf_->Purge(display_comp_ctx->display_resource_ctx);
    378 
    379   display_comp_ctx->strategy->Purge();
    380 }
    381 
    382 DisplayError CompManager::SetIdleTimeoutMs(Handle display_ctx, uint32_t active_ms) {
    383   SCOPE_LOCK(locker_);
    384 
    385   DisplayCompositionContext *display_comp_ctx =
    386                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    387 
    388   return display_comp_ctx->strategy->SetIdleTimeoutMs(active_ms);
    389 }
    390 
    391 void CompManager::ProcessIdleTimeout(Handle display_ctx) {
    392   SCOPE_LOCK(locker_);
    393 
    394   DisplayCompositionContext *display_comp_ctx =
    395                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    396 
    397   if (!display_comp_ctx) {
    398     return;
    399   }
    400 
    401   display_comp_ctx->idle_fallback = true;
    402 }
    403 
    404 void CompManager::ProcessThermalEvent(Handle display_ctx, int64_t thermal_level) {
    405   SCOPE_LOCK(locker_);
    406 
    407   DisplayCompositionContext *display_comp_ctx =
    408           reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    409 
    410   if (thermal_level >= kMaxThermalLevel) {
    411     display_comp_ctx->thermal_fallback_ = true;
    412   } else {
    413     display_comp_ctx->thermal_fallback_ = false;
    414   }
    415 }
    416 
    417 void CompManager::ProcessIdlePowerCollapse(Handle display_ctx) {
    418   SCOPE_LOCK(locker_);
    419 
    420   DisplayCompositionContext *display_comp_ctx =
    421           reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    422 
    423   if (display_comp_ctx) {
    424     resource_intf_->Perform(ResourceInterface::kCmdResetScalarLUT,
    425                             display_comp_ctx->display_resource_ctx);
    426   }
    427 }
    428 
    429 DisplayError CompManager::SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) {
    430   SCOPE_LOCK(locker_);
    431 
    432   DisplayError error = kErrorNone;
    433   DisplayCompositionContext *display_comp_ctx =
    434                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    435 
    436   if (display_comp_ctx) {
    437     error = resource_intf_->SetMaxMixerStages(display_comp_ctx->display_resource_ctx,
    438                                               max_mixer_stages);
    439   }
    440 
    441   return error;
    442 }
    443 
    444 void CompManager::ControlPartialUpdate(Handle display_ctx, bool enable) {
    445   SCOPE_LOCK(locker_);
    446 
    447   DisplayCompositionContext *display_comp_ctx =
    448                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    449   display_comp_ctx->pu_constraints.enable = enable;
    450 }
    451 
    452 void CompManager::AppendDump(char *buffer, uint32_t length) {
    453   SCOPE_LOCK(locker_);
    454 }
    455 
    456 DisplayError CompManager::ValidateScaling(const LayerRect &crop, const LayerRect &dst,
    457                                           bool rotate90) {
    458   BufferLayout layout = Debug::IsUbwcTiledFrameBuffer() ? kUBWC : kLinear;
    459   return resource_intf_->ValidateScaling(crop, dst, rotate90, layout, true);
    460 }
    461 
    462 DisplayError CompManager::ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers,
    463                                                  int x, int y) {
    464   DisplayCompositionContext *display_comp_ctx =
    465                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    466   Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
    467 
    468   return resource_intf_->ValidateCursorPosition(display_resource_ctx, hw_layers, x, y);
    469 }
    470 
    471 DisplayError CompManager::SetMaxBandwidthMode(HWBwModes mode) {
    472   if ((hw_res_info_.has_dyn_bw_support == false) || (mode >= kBwModeMax)) {
    473     return kErrorNotSupported;
    474   }
    475 
    476   return resource_intf_->SetMaxBandwidthMode(mode);
    477 }
    478 
    479 DisplayError CompManager::GetScaleLutConfig(HWScaleLutInfo *lut_info) {
    480   return resource_intf_->GetScaleLutConfig(lut_info);
    481 }
    482 
    483 DisplayError CompManager::SetDetailEnhancerData(Handle display_ctx,
    484                                                 const DisplayDetailEnhancerData &de_data) {
    485   SCOPE_LOCK(locker_);
    486 
    487   DisplayCompositionContext *display_comp_ctx =
    488                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    489 
    490   return resource_intf_->SetDetailEnhancerData(display_comp_ctx->display_resource_ctx, de_data);
    491 }
    492 
    493 DisplayError CompManager::SetCompositionState(Handle display_ctx,
    494                                               LayerComposition composition_type, bool enable) {
    495   SCOPE_LOCK(locker_);
    496 
    497   DisplayCompositionContext *display_comp_ctx =
    498                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    499 
    500   return display_comp_ctx->strategy->SetCompositionState(composition_type, enable);
    501 }
    502 
    503 DisplayError CompManager::ControlDpps(bool enable) {
    504   if (dpps_ctrl_intf_) {
    505     return enable ? dpps_ctrl_intf_->On() : dpps_ctrl_intf_->Off();
    506   }
    507 
    508   return kErrorNone;
    509 }
    510 
    511 bool CompManager::SetDisplayState(Handle display_ctx,
    512                                   DisplayState state, DisplayType display_type) {
    513   display_state_[display_type] = state;
    514 
    515   switch (state) {
    516   case kStateOff:
    517     Purge(display_ctx);
    518     configured_displays_.reset(display_type);
    519     DLOGV_IF(kTagCompManager, "configured_displays_ = 0x%x", configured_displays_);
    520     break;
    521 
    522   case kStateOn:
    523     if (registered_displays_.count() > 1) {
    524       safe_mode_ = true;
    525       DLOGV_IF(kTagCompManager, "safe_mode = %d", safe_mode_);
    526     }
    527     break;
    528 
    529   default:
    530     break;
    531   }
    532 
    533   return true;
    534 }
    535 
    536 }  // namespace sdm
    537