Home | History | Annotate | Download | only in core
      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 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                                BufferSyncHandler *buffer_sync_handler) {
     39   SCOPE_LOCK(locker_);
     40 
     41   DisplayError error = kErrorNone;
     42 
     43   if (extension_intf) {
     44     error = extension_intf->CreateResourceExtn(hw_res_info, &resource_intf_, buffer_sync_handler);
     45   } else {
     46     resource_intf_ = &resource_default_;
     47     error = resource_default_.Init(hw_res_info);
     48   }
     49 
     50   if (error != kErrorNone) {
     51     return error;
     52   }
     53 
     54   hw_res_info_ = hw_res_info;
     55   extension_intf_ = extension_intf;
     56 
     57   return error;
     58 }
     59 
     60 DisplayError CompManager::Deinit() {
     61   SCOPE_LOCK(locker_);
     62 
     63   if (extension_intf_) {
     64     extension_intf_->DestroyResourceExtn(resource_intf_);
     65   } else {
     66     resource_default_.Deinit();
     67   }
     68 
     69   return kErrorNone;
     70 }
     71 
     72 DisplayError CompManager::RegisterDisplay(DisplayType type,
     73                                           const HWDisplayAttributes &display_attributes,
     74                                           const HWPanelInfo &hw_panel_info,
     75                                           const HWMixerAttributes &mixer_attributes,
     76                                           const DisplayConfigVariableInfo &fb_config,
     77                                           Handle *display_ctx) {
     78   SCOPE_LOCK(locker_);
     79 
     80   DisplayError error = kErrorNone;
     81 
     82   DisplayCompositionContext *display_comp_ctx = new DisplayCompositionContext();
     83   if (!display_comp_ctx) {
     84     return kErrorMemory;
     85   }
     86 
     87   Strategy *&strategy = display_comp_ctx->strategy;
     88   strategy = new Strategy(extension_intf_, type, hw_res_info_, hw_panel_info, mixer_attributes,
     89                           display_attributes, fb_config);
     90   if (!strategy) {
     91     DLOGE("Unable to create strategy");
     92     delete display_comp_ctx;
     93     return kErrorMemory;
     94   }
     95 
     96   error = strategy->Init();
     97   if (error != kErrorNone) {
     98     delete strategy;
     99     delete display_comp_ctx;
    100     return error;
    101   }
    102 
    103   error = resource_intf_->RegisterDisplay(type, display_attributes, hw_panel_info, mixer_attributes,
    104                                           &display_comp_ctx->display_resource_ctx);
    105   if (error != kErrorNone) {
    106     strategy->Deinit();
    107     delete strategy;
    108     delete display_comp_ctx;
    109     display_comp_ctx = NULL;
    110     return error;
    111   }
    112 
    113   registered_displays_[type] = 1;
    114   display_comp_ctx->is_primary_panel = hw_panel_info.is_primary_panel;
    115   display_comp_ctx->display_type = type;
    116   *display_ctx = display_comp_ctx;
    117   // New non-primary display device has been added, so move the composition mode to safe mode until
    118   // resources for the added display is configured properly.
    119   if (!display_comp_ctx->is_primary_panel) {
    120     safe_mode_ = true;
    121   }
    122 
    123   DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
    124            "display type %d", registered_displays_.to_ulong(), configured_displays_.to_ulong(),
    125            display_comp_ctx->display_type);
    126 
    127   return kErrorNone;
    128 }
    129 
    130 DisplayError CompManager::UnregisterDisplay(Handle comp_handle) {
    131   SCOPE_LOCK(locker_);
    132 
    133   DisplayCompositionContext *display_comp_ctx =
    134                              reinterpret_cast<DisplayCompositionContext *>(comp_handle);
    135 
    136   if (!display_comp_ctx) {
    137     return kErrorParameters;
    138   }
    139 
    140   resource_intf_->UnregisterDisplay(display_comp_ctx->display_resource_ctx);
    141 
    142   Strategy *&strategy = display_comp_ctx->strategy;
    143   strategy->Deinit();
    144   delete strategy;
    145 
    146   registered_displays_[display_comp_ctx->display_type] = 0;
    147   configured_displays_[display_comp_ctx->display_type] = 0;
    148 
    149   if (display_comp_ctx->display_type == kHDMI) {
    150     max_layers_ = kMaxSDELayers;
    151   }
    152 
    153   DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
    154            "display type %d", registered_displays_.to_ulong(), configured_displays_.to_ulong(),
    155            display_comp_ctx->display_type);
    156 
    157   delete display_comp_ctx;
    158   display_comp_ctx = NULL;
    159   return kErrorNone;
    160 }
    161 
    162 DisplayError CompManager::ReconfigureDisplay(Handle comp_handle,
    163                                              const HWDisplayAttributes &display_attributes,
    164                                              const HWPanelInfo &hw_panel_info,
    165                                              const HWMixerAttributes &mixer_attributes,
    166                                              const DisplayConfigVariableInfo &fb_config) {
    167   SCOPE_LOCK(locker_);
    168 
    169   DisplayError error = kErrorNone;
    170   DisplayCompositionContext *display_comp_ctx =
    171                              reinterpret_cast<DisplayCompositionContext *>(comp_handle);
    172 
    173   error = resource_intf_->ReconfigureDisplay(display_comp_ctx->display_resource_ctx,
    174                                              display_attributes, hw_panel_info, mixer_attributes);
    175   if (error != kErrorNone) {
    176     return error;
    177   }
    178 
    179   if (display_comp_ctx->strategy) {
    180     error = display_comp_ctx->strategy->Reconfigure(hw_panel_info, display_attributes,
    181                                                     mixer_attributes, fb_config);
    182     if (error != kErrorNone) {
    183       DLOGE("Unable to Reconfigure strategy.");
    184       display_comp_ctx->strategy->Deinit();
    185       delete display_comp_ctx->strategy;
    186       display_comp_ctx->strategy = NULL;
    187       return error;
    188     }
    189   }
    190 
    191   // For HDMI S3D mode, set max_layers_ to 0 so that primary display would fall back
    192   // to GPU composition to release pipes for HDMI.
    193   if (display_comp_ctx->display_type == kHDMI) {
    194     if (hw_panel_info.s3d_mode != kS3DModeNone) {
    195       max_layers_ = 0;
    196     } else {
    197       max_layers_ = kMaxSDELayers;
    198     }
    199   }
    200 
    201   return error;
    202 }
    203 
    204 void CompManager::PrepareStrategyConstraints(Handle comp_handle, HWLayers *hw_layers) {
    205   DisplayCompositionContext *display_comp_ctx =
    206                              reinterpret_cast<DisplayCompositionContext *>(comp_handle);
    207   StrategyConstraints *constraints = &display_comp_ctx->constraints;
    208 
    209   constraints->safe_mode = safe_mode_;
    210   constraints->use_cursor = false;
    211   constraints->max_layers = max_layers_;
    212 
    213   // Limit 2 layer SDE Comp if its not a Primary Display
    214   if (!display_comp_ctx->is_primary_panel) {
    215     constraints->max_layers = 2;
    216   }
    217 
    218   // If a strategy fails after successfully allocating resources, then set safe mode
    219   if (display_comp_ctx->remaining_strategies != display_comp_ctx->max_strategies) {
    220     constraints->safe_mode = true;
    221   }
    222 
    223   // Avoid idle fallback, if there is only one app layer.
    224   // TODO(user): App layer count will change for hybrid composition
    225   uint32_t app_layer_count = UINT32(hw_layers->info.stack->layers.size()) - 1;
    226   if ((app_layer_count > 1 && display_comp_ctx->idle_fallback) || display_comp_ctx->fallback_) {
    227     // Handle the idle timeout by falling back
    228     constraints->safe_mode = true;
    229   }
    230 
    231   if (SupportLayerAsCursor(comp_handle, hw_layers)) {
    232     constraints->use_cursor = true;
    233   }
    234 }
    235 
    236 void CompManager::PrePrepare(Handle display_ctx, HWLayers *hw_layers) {
    237   SCOPE_LOCK(locker_);
    238   DisplayCompositionContext *display_comp_ctx =
    239                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    240   display_comp_ctx->strategy->Start(&hw_layers->info, &display_comp_ctx->max_strategies,
    241                                     display_comp_ctx->partial_update_enable);
    242   display_comp_ctx->remaining_strategies = display_comp_ctx->max_strategies;
    243 }
    244 
    245 DisplayError CompManager::Prepare(Handle display_ctx, HWLayers *hw_layers) {
    246   SCOPE_LOCK(locker_);
    247 
    248   DisplayCompositionContext *display_comp_ctx =
    249                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    250   Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
    251 
    252   DisplayError error = kErrorUndefined;
    253 
    254   PrepareStrategyConstraints(display_ctx, hw_layers);
    255 
    256   // Select a composition strategy, and try to allocate resources for it.
    257   resource_intf_->Start(display_resource_ctx);
    258 
    259   bool exit = false;
    260   uint32_t &count = display_comp_ctx->remaining_strategies;
    261   for (; !exit && count > 0; count--) {
    262     error = display_comp_ctx->strategy->GetNextStrategy(&display_comp_ctx->constraints);
    263     if (error != kErrorNone) {
    264       // Composition strategies exhausted. Resource Manager could not allocate resources even for
    265       // GPU composition. This will never happen.
    266       exit = true;
    267     }
    268 
    269     if (!exit) {
    270       error = resource_intf_->Acquire(display_resource_ctx, hw_layers);
    271       // Exit if successfully allocated resource, else try next strategy.
    272       exit = (error == kErrorNone);
    273     }
    274   }
    275 
    276   if (error != kErrorNone) {
    277     DLOGE("Composition strategies exhausted for display = %d", display_comp_ctx->display_type);
    278   }
    279 
    280   resource_intf_->Stop(display_resource_ctx);
    281 
    282   return error;
    283 }
    284 
    285 DisplayError CompManager::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
    286   SCOPE_LOCK(locker_);
    287   DisplayCompositionContext *display_comp_ctx =
    288                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    289   Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
    290 
    291   DisplayError error = kErrorNone;
    292   error = resource_intf_->PostPrepare(display_resource_ctx, hw_layers);
    293   if (error != kErrorNone) {
    294     return error;
    295   }
    296 
    297   display_comp_ctx->strategy->Stop();
    298 
    299   return kErrorNone;
    300 }
    301 
    302 DisplayError CompManager::ReConfigure(Handle display_ctx, HWLayers *hw_layers) {
    303   SCOPE_LOCK(locker_);
    304 
    305   DisplayCompositionContext *display_comp_ctx =
    306                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    307   Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
    308 
    309   DisplayError error = kErrorUndefined;
    310   resource_intf_->Start(display_resource_ctx);
    311   error = resource_intf_->Acquire(display_resource_ctx, hw_layers);
    312 
    313   if (error != kErrorNone) {
    314     DLOGE("Reconfigure failed for display = %d", display_comp_ctx->display_type);
    315   }
    316 
    317   resource_intf_->Stop(display_resource_ctx);
    318   if (error != kErrorNone) {
    319       error = resource_intf_->PostPrepare(display_resource_ctx, hw_layers);
    320   }
    321 
    322   return error;
    323 }
    324 
    325 DisplayError CompManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
    326   SCOPE_LOCK(locker_);
    327 
    328   DisplayError error = kErrorNone;
    329   DisplayCompositionContext *display_comp_ctx =
    330                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    331   configured_displays_[display_comp_ctx->display_type] = 1;
    332   if (configured_displays_ == registered_displays_) {
    333     safe_mode_ = false;
    334   }
    335 
    336   error = resource_intf_->PostCommit(display_comp_ctx->display_resource_ctx, hw_layers);
    337   if (error != kErrorNone) {
    338     return error;
    339   }
    340 
    341   display_comp_ctx->idle_fallback = false;
    342 
    343   DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
    344            "display type %d", registered_displays_, configured_displays_,
    345            display_comp_ctx->display_type);
    346 
    347   return kErrorNone;
    348 }
    349 
    350 void CompManager::Purge(Handle display_ctx) {
    351   SCOPE_LOCK(locker_);
    352 
    353   DisplayCompositionContext *display_comp_ctx =
    354                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    355 
    356   resource_intf_->Purge(display_comp_ctx->display_resource_ctx);
    357 }
    358 
    359 void CompManager::ProcessIdleTimeout(Handle display_ctx) {
    360   SCOPE_LOCK(locker_);
    361 
    362   DisplayCompositionContext *display_comp_ctx =
    363                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    364 
    365   if (!display_comp_ctx) {
    366     return;
    367   }
    368 
    369   display_comp_ctx->idle_fallback = true;
    370 }
    371 
    372 void CompManager::ProcessThermalEvent(Handle display_ctx, int64_t thermal_level) {
    373   SCOPE_LOCK(locker_);
    374 
    375   DisplayCompositionContext *display_comp_ctx =
    376           reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    377 
    378   if (thermal_level >= kMaxThermalLevel) {
    379     display_comp_ctx->fallback_ = true;
    380   } else {
    381     display_comp_ctx->fallback_ = false;
    382   }
    383 }
    384 
    385 DisplayError CompManager::SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) {
    386   SCOPE_LOCK(locker_);
    387 
    388   DisplayError error = kErrorNone;
    389   DisplayCompositionContext *display_comp_ctx =
    390                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    391 
    392   if (display_comp_ctx) {
    393     error = resource_intf_->SetMaxMixerStages(display_comp_ctx->display_resource_ctx,
    394                                               max_mixer_stages);
    395   }
    396 
    397   return error;
    398 }
    399 
    400 void CompManager::ControlPartialUpdate(Handle display_ctx, bool enable) {
    401   SCOPE_LOCK(locker_);
    402 
    403   DisplayCompositionContext *display_comp_ctx =
    404                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    405   display_comp_ctx->partial_update_enable = enable;
    406 }
    407 
    408 void CompManager::AppendDump(char *buffer, uint32_t length) {
    409   SCOPE_LOCK(locker_);
    410 }
    411 
    412 DisplayError CompManager::ValidateScaling(const LayerRect &crop, const LayerRect &dst,
    413                                           bool rotate90) {
    414   return resource_intf_->ValidateScaling(crop, dst, rotate90, Debug::IsUbwcTiledFrameBuffer(),
    415                                          true /* use_rotator_downscale */);
    416 }
    417 
    418 DisplayError CompManager::ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers,
    419                                                  int x, int y) {
    420   DisplayCompositionContext *display_comp_ctx =
    421                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    422   Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
    423 
    424   return resource_intf_->ValidateCursorPosition(display_resource_ctx, hw_layers, x, y);
    425 }
    426 
    427 bool CompManager::SupportLayerAsCursor(Handle comp_handle, HWLayers *hw_layers) {
    428   DisplayCompositionContext *display_comp_ctx =
    429                              reinterpret_cast<DisplayCompositionContext *>(comp_handle);
    430   Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
    431   LayerStack *layer_stack = hw_layers->info.stack;
    432   bool supported = false;
    433   int32_t gpu_index = -1;
    434 
    435   if (!layer_stack->flags.cursor_present) {
    436     return supported;
    437   }
    438 
    439   for (int32_t i = INT32(layer_stack->layers.size() - 1); i >= 0; i--) {
    440     Layer *layer = layer_stack->layers.at(UINT32(i));
    441     if (layer->composition == kCompositionGPUTarget) {
    442       gpu_index = i;
    443       break;
    444     }
    445   }
    446   if (gpu_index <= 0) {
    447     return supported;
    448   }
    449   Layer *cursor_layer = layer_stack->layers.at(UINT32(gpu_index) - 1);
    450   if (cursor_layer->flags.cursor && resource_intf_->ValidateCursorConfig(display_resource_ctx,
    451                                     cursor_layer, true) == kErrorNone) {
    452     supported = true;
    453   }
    454 
    455   return supported;
    456 }
    457 
    458 DisplayError CompManager::SetMaxBandwidthMode(HWBwModes mode) {
    459   if ((hw_res_info_.has_dyn_bw_support == false) || (mode >= kBwModeMax)) {
    460     return kErrorNotSupported;
    461   }
    462 
    463   return resource_intf_->SetMaxBandwidthMode(mode);
    464 }
    465 
    466 bool CompManager::CanSetIdleTimeout(Handle display_ctx) {
    467   DisplayCompositionContext *display_comp_ctx =
    468                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    469 
    470   if (!display_comp_ctx) {
    471     return false;
    472   }
    473 
    474   if (!display_comp_ctx->idle_fallback) {
    475     return true;
    476   }
    477 
    478   return false;
    479 }
    480 
    481 DisplayError CompManager::GetScaleLutConfig(HWScaleLutInfo *lut_info) {
    482   return resource_intf_->GetScaleLutConfig(lut_info);
    483 }
    484 
    485 DisplayError CompManager::SetDetailEnhancerData(Handle display_ctx,
    486                                                 const DisplayDetailEnhancerData &de_data) {
    487   SCOPE_LOCK(locker_);
    488 
    489   DisplayCompositionContext *display_comp_ctx =
    490                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
    491 
    492   return resource_intf_->SetDetailEnhancerData(display_comp_ctx->display_resource_ctx, de_data);
    493 }
    494 
    495 }  // namespace sdm
    496 
    497