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 <math.h>
     26 #include <utils/constants.h>
     27 #include <utils/debug.h>
     28 #include <utils/rect.h>
     29 #include <utils/formats.h>
     30 #include <utils/sys.h>
     31 #include <dlfcn.h>
     32 #include <algorithm>
     33 
     34 #include "resource_default.h"
     35 
     36 #define __CLASS__ "ResourceDefault"
     37 
     38 namespace sdm {
     39 
     40 DisplayError ResourceDefault::CreateResourceDefault(const HWResourceInfo &hw_resource_info,
     41                                                     ResourceInterface **resource_intf) {
     42   DisplayError error = kErrorNone;
     43 
     44   ResourceDefault *resource_default = new ResourceDefault(hw_resource_info);
     45   if (!resource_default) {
     46     return kErrorNone;
     47   }
     48 
     49   error = resource_default->Init();
     50   if (error != kErrorNone) {
     51     delete resource_default;
     52   }
     53 
     54   *resource_intf = resource_default;
     55 
     56   return kErrorNone;
     57 }
     58 
     59 DisplayError ResourceDefault::DestroyResourceDefault(ResourceInterface *resource_intf) {
     60   ResourceDefault *resource_default = static_cast<ResourceDefault *>(resource_intf);
     61 
     62   resource_default->Deinit();
     63   delete resource_default;
     64 
     65   return kErrorNone;
     66 }
     67 
     68 ResourceDefault::ResourceDefault(const HWResourceInfo &hw_res_info)
     69   : hw_res_info_(hw_res_info) {
     70 }
     71 
     72 DisplayError ResourceDefault::Init() {
     73   DisplayError error = kErrorNone;
     74 
     75   num_pipe_ = hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe + hw_res_info_.num_dma_pipe;
     76 
     77   if (!num_pipe_) {
     78     DLOGE("Number of H/W pipes is Zero!");
     79     return kErrorParameters;
     80   }
     81 
     82   src_pipes_.resize(num_pipe_);
     83 
     84   // Priority order of pipes: VIG, RGB, DMA
     85   uint32_t vig_index = 0;
     86   uint32_t rgb_index = hw_res_info_.num_vig_pipe;
     87   uint32_t dma_index = rgb_index + hw_res_info_.num_rgb_pipe;
     88 
     89   for (uint32_t i = 0; i < num_pipe_; i++) {
     90     const HWPipeCaps &pipe_caps = hw_res_info_.hw_pipes.at(i);
     91     if (pipe_caps.type == kPipeTypeVIG) {
     92       src_pipes_[vig_index].type = kPipeTypeVIG;
     93       src_pipes_[vig_index].index = i;
     94       src_pipes_[vig_index].mdss_pipe_id = pipe_caps.id;
     95       vig_index++;
     96     } else if (pipe_caps.type == kPipeTypeRGB) {
     97       src_pipes_[rgb_index].type = kPipeTypeRGB;
     98       src_pipes_[rgb_index].index = i;
     99       src_pipes_[rgb_index].mdss_pipe_id = pipe_caps.id;
    100       rgb_index++;
    101     } else if (pipe_caps.type == kPipeTypeDMA) {
    102       src_pipes_[dma_index].type = kPipeTypeDMA;
    103       src_pipes_[dma_index].index = i;
    104       src_pipes_[dma_index].mdss_pipe_id = pipe_caps.id;
    105       dma_index++;
    106     }
    107   }
    108 
    109   for (uint32_t i = 0; i < num_pipe_; i++) {
    110     src_pipes_[i].priority = INT(i);
    111   }
    112 
    113   DLOGI("hw_rev=%x, DMA=%d RGB=%d VIG=%d", hw_res_info_.hw_revision, hw_res_info_.num_dma_pipe,
    114     hw_res_info_.num_rgb_pipe, hw_res_info_.num_vig_pipe);
    115 
    116   if (hw_res_info_.max_scale_down < 1 || hw_res_info_.max_scale_up < 1) {
    117     DLOGE("Max scaling setting is invalid! max_scale_down = %d, max_scale_up = %d",
    118           hw_res_info_.max_scale_down, hw_res_info_.max_scale_up);
    119     hw_res_info_.max_scale_down = 1;
    120     hw_res_info_.max_scale_up = 1;
    121   }
    122 
    123   // TODO(user): clean it up, query from driver for initial pipe status.
    124 #ifndef SDM_VIRTUAL_DRIVER
    125   rgb_index = hw_res_info_.num_vig_pipe;
    126   src_pipes_[rgb_index].owner = kPipeOwnerKernelMode;
    127   src_pipes_[rgb_index + 1].owner = kPipeOwnerKernelMode;
    128 #endif
    129 
    130   return error;
    131 }
    132 
    133 DisplayError ResourceDefault::Deinit() {
    134   return kErrorNone;
    135 }
    136 
    137 DisplayError ResourceDefault::RegisterDisplay(DisplayType type,
    138                                               const HWDisplayAttributes &display_attributes,
    139                                               const HWPanelInfo &hw_panel_info,
    140                                               const HWMixerAttributes &mixer_attributes,
    141                                               Handle *display_ctx) {
    142   DisplayError error = kErrorNone;
    143 
    144   HWBlockType hw_block_id = kHWBlockMax;
    145   switch (type) {
    146   case kPrimary:
    147     if (!hw_block_ctx_[kHWPrimary].is_in_use) {
    148       hw_block_id = kHWPrimary;
    149     }
    150     break;
    151 
    152   case kHDMI:
    153     if (!hw_block_ctx_[kHWHDMI].is_in_use) {
    154       hw_block_id = kHWHDMI;
    155     }
    156     break;
    157 
    158   default:
    159     DLOGW("RegisterDisplay, invalid type %d", type);
    160     return kErrorParameters;
    161   }
    162 
    163   if (hw_block_id == kHWBlockMax) {
    164     return kErrorResources;
    165   }
    166 
    167   DisplayResourceContext *display_resource_ctx = new DisplayResourceContext();
    168   if (!display_resource_ctx) {
    169     return kErrorMemory;
    170   }
    171 
    172   hw_block_ctx_[hw_block_id].is_in_use = true;
    173 
    174   display_resource_ctx->display_attributes = display_attributes;
    175   display_resource_ctx->hw_block_id = hw_block_id;
    176   display_resource_ctx->mixer_attributes = mixer_attributes;
    177 
    178   *display_ctx = display_resource_ctx;
    179   return error;
    180 }
    181 
    182 DisplayError ResourceDefault::UnregisterDisplay(Handle display_ctx) {
    183   DisplayResourceContext *display_resource_ctx =
    184                           reinterpret_cast<DisplayResourceContext *>(display_ctx);
    185   Purge(display_ctx);
    186 
    187   hw_block_ctx_[display_resource_ctx->hw_block_id].is_in_use = false;
    188 
    189   delete display_resource_ctx;
    190 
    191   return kErrorNone;
    192 }
    193 
    194 DisplayError ResourceDefault::ReconfigureDisplay(Handle display_ctx,
    195                                                  const HWDisplayAttributes &display_attributes,
    196                                                  const HWPanelInfo &hw_panel_info,
    197                                                  const HWMixerAttributes &mixer_attributes) {
    198   SCOPE_LOCK(locker_);
    199 
    200   DisplayResourceContext *display_resource_ctx =
    201                           reinterpret_cast<DisplayResourceContext *>(display_ctx);
    202 
    203   display_resource_ctx->display_attributes = display_attributes;
    204   display_resource_ctx->mixer_attributes = mixer_attributes;
    205 
    206   return kErrorNone;
    207 }
    208 
    209 DisplayError ResourceDefault::Start(Handle display_ctx) {
    210   locker_.Lock();
    211 
    212   return kErrorNone;
    213 }
    214 
    215 DisplayError ResourceDefault::Stop(Handle display_ctx) {
    216   locker_.Unlock();
    217 
    218   return kErrorNone;
    219 }
    220 
    221 DisplayError ResourceDefault::Prepare(Handle display_ctx, HWLayers *hw_layers) {
    222   DisplayResourceContext *display_resource_ctx =
    223                           reinterpret_cast<DisplayResourceContext *>(display_ctx);
    224 
    225   DisplayError error = kErrorNone;
    226   const struct HWLayersInfo &layer_info = hw_layers->info;
    227   HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
    228 
    229   DLOGV_IF(kTagResources, "==== Resource reserving start: hw_block = %d ====", hw_block_id);
    230 
    231   if (layer_info.hw_layers.size() > 1) {
    232     DLOGV_IF(kTagResources, "More than one FB layers");
    233     return kErrorResources;
    234   }
    235 
    236   const Layer &layer = layer_info.hw_layers.at(0);
    237 
    238   if (layer.composition != kCompositionGPUTarget) {
    239     DLOGV_IF(kTagResources, "Not an FB layer");
    240     return kErrorParameters;
    241   }
    242 
    243   error = Config(display_resource_ctx, hw_layers);
    244   if (error != kErrorNone) {
    245     DLOGV_IF(kTagResources, "Resource config failed");
    246     return error;
    247   }
    248 
    249   for (uint32_t i = 0; i < num_pipe_; i++) {
    250     if (src_pipes_[i].hw_block_id == hw_block_id && src_pipes_[i].owner == kPipeOwnerUserMode) {
    251       src_pipes_[i].ResetState();
    252     }
    253   }
    254 
    255   uint32_t left_index = num_pipe_;
    256   uint32_t right_index = num_pipe_;
    257   bool need_scale = false;
    258 
    259   struct HWLayerConfig &layer_config = hw_layers->config[0];
    260 
    261   HWPipeInfo *left_pipe = &layer_config.left_pipe;
    262   HWPipeInfo *right_pipe = &layer_config.right_pipe;
    263 
    264   // left pipe is needed
    265   if (left_pipe->valid) {
    266     need_scale = IsScalingNeeded(left_pipe);
    267     left_index = GetPipe(hw_block_id, need_scale);
    268     if (left_index >= num_pipe_) {
    269       DLOGV_IF(kTagResources, "Get left pipe failed: hw_block_id = %d, need_scale = %d",
    270                hw_block_id, need_scale);
    271       ResourceStateLog();
    272       goto CleanupOnError;
    273     }
    274   }
    275 
    276   error = SetDecimationFactor(left_pipe);
    277   if (error != kErrorNone) {
    278     goto CleanupOnError;
    279   }
    280 
    281   if (!right_pipe->valid) {
    282     // assign single pipe
    283     if (left_index < num_pipe_) {
    284       left_pipe->pipe_id = src_pipes_[left_index].mdss_pipe_id;
    285     }
    286     DLOGV_IF(kTagResources, "1 pipe acquired for FB layer, left_pipe = %x", left_pipe->pipe_id);
    287     return kErrorNone;
    288   }
    289 
    290   need_scale = IsScalingNeeded(right_pipe);
    291 
    292   right_index = GetPipe(hw_block_id, need_scale);
    293   if (right_index >= num_pipe_) {
    294     DLOGV_IF(kTagResources, "Get right pipe failed: hw_block_id = %d, need_scale = %d", hw_block_id,
    295              need_scale);
    296     ResourceStateLog();
    297     goto CleanupOnError;
    298   }
    299 
    300   if (src_pipes_[right_index].priority < src_pipes_[left_index].priority) {
    301     // Swap pipe based on priority
    302     std::swap(left_index, right_index);
    303   }
    304 
    305   // assign dual pipes
    306   left_pipe->pipe_id = src_pipes_[left_index].mdss_pipe_id;
    307   right_pipe->pipe_id = src_pipes_[right_index].mdss_pipe_id;
    308 
    309   error = SetDecimationFactor(right_pipe);
    310   if (error != kErrorNone) {
    311     goto CleanupOnError;
    312   }
    313 
    314   DLOGV_IF(kTagResources, "2 pipes acquired for FB layer, left_pipe = %x, right_pipe = %x",
    315            left_pipe->pipe_id,  right_pipe->pipe_id);
    316 
    317   return kErrorNone;
    318 
    319 CleanupOnError:
    320   DLOGV_IF(kTagResources, "Resource reserving failed! hw_block = %d", hw_block_id);
    321 
    322   return kErrorResources;
    323 }
    324 
    325 DisplayError ResourceDefault::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
    326   SCOPE_LOCK(locker_);
    327 
    328   return kErrorNone;
    329 }
    330 
    331 DisplayError ResourceDefault::Commit(Handle display_ctx, HWLayers *hw_layers) {
    332   SCOPE_LOCK(locker_);
    333 
    334   return kErrorNone;
    335 }
    336 
    337 DisplayError ResourceDefault::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
    338   SCOPE_LOCK(locker_);
    339   DisplayResourceContext *display_resource_ctx =
    340                           reinterpret_cast<DisplayResourceContext *>(display_ctx);
    341   HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
    342   uint64_t frame_count = display_resource_ctx->frame_count;
    343 
    344   DLOGV_IF(kTagResources, "Resource for hw_block = %d, frame_count = %d", hw_block_id, frame_count);
    345 
    346   // handoff pipes which are used by splash screen
    347   if ((frame_count == 0) && (hw_block_id == kHWPrimary)) {
    348     for (uint32_t i = 0; i < num_pipe_; i++) {
    349       if (src_pipes_[i].hw_block_id == hw_block_id && src_pipes_[i].owner == kPipeOwnerKernelMode) {
    350         src_pipes_[i].owner = kPipeOwnerUserMode;
    351       }
    352     }
    353   }
    354 
    355   if (hw_layers->info.sync_handle >= 0)
    356     Sys::close_(hw_layers->info.sync_handle);
    357 
    358   display_resource_ctx->frame_count++;
    359 
    360   return kErrorNone;
    361 }
    362 
    363 void ResourceDefault::Purge(Handle display_ctx) {
    364   SCOPE_LOCK(locker_);
    365 
    366   DisplayResourceContext *display_resource_ctx =
    367                           reinterpret_cast<DisplayResourceContext *>(display_ctx);
    368   HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
    369 
    370   for (uint32_t i = 0; i < num_pipe_; i++) {
    371     if (src_pipes_[i].hw_block_id == hw_block_id && src_pipes_[i].owner == kPipeOwnerUserMode) {
    372       src_pipes_[i].ResetState();
    373     }
    374   }
    375   DLOGV_IF(kTagResources, "display id = %d", display_resource_ctx->hw_block_id);
    376 }
    377 
    378 DisplayError ResourceDefault::SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) {
    379   SCOPE_LOCK(locker_);
    380 
    381   return kErrorNone;
    382 }
    383 
    384 uint32_t ResourceDefault::SearchPipe(HWBlockType hw_block_id, SourcePipe *src_pipes,
    385                                 uint32_t num_pipe) {
    386   uint32_t index = num_pipe_;
    387   SourcePipe *src_pipe;
    388 
    389   // search the pipe being used
    390   for (uint32_t i = 0; i < num_pipe; i++) {
    391     src_pipe = &src_pipes[i];
    392     if (src_pipe->owner == kPipeOwnerUserMode && src_pipe->hw_block_id == kHWBlockMax) {
    393       index = src_pipe->index;
    394       src_pipe->hw_block_id = hw_block_id;
    395       break;
    396     }
    397   }
    398 
    399   return index;
    400 }
    401 
    402 uint32_t ResourceDefault::NextPipe(PipeType type, HWBlockType hw_block_id) {
    403   uint32_t num_pipe = 0;
    404   SourcePipe *src_pipes = NULL;
    405 
    406   switch (type) {
    407   case kPipeTypeVIG:
    408     src_pipes = &src_pipes_[0];
    409     num_pipe = hw_res_info_.num_vig_pipe;
    410     break;
    411   case kPipeTypeRGB:
    412     src_pipes = &src_pipes_[hw_res_info_.num_vig_pipe];
    413     num_pipe = hw_res_info_.num_rgb_pipe;
    414     break;
    415   case kPipeTypeDMA:
    416   default:
    417     src_pipes = &src_pipes_[hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe];
    418     num_pipe = hw_res_info_.num_dma_pipe;
    419     break;
    420   }
    421 
    422   return SearchPipe(hw_block_id, src_pipes, num_pipe);
    423 }
    424 
    425 uint32_t ResourceDefault::GetPipe(HWBlockType hw_block_id, bool need_scale) {
    426   uint32_t index = num_pipe_;
    427 
    428   // The default behavior is to assume RGB and VG pipes have scalars
    429   if (!need_scale) {
    430     index = NextPipe(kPipeTypeDMA, hw_block_id);
    431   }
    432 
    433   if ((index >= num_pipe_) && (!need_scale || !hw_res_info_.has_non_scalar_rgb)) {
    434     index = NextPipe(kPipeTypeRGB, hw_block_id);
    435   }
    436 
    437   if (index >= num_pipe_) {
    438     index = NextPipe(kPipeTypeVIG, hw_block_id);
    439   }
    440 
    441   return index;
    442 }
    443 
    444 bool ResourceDefault::IsScalingNeeded(const HWPipeInfo *pipe_info) {
    445   const LayerRect &src_roi = pipe_info->src_roi;
    446   const LayerRect &dst_roi = pipe_info->dst_roi;
    447 
    448   return ((dst_roi.right - dst_roi.left) != (src_roi.right - src_roi.left)) ||
    449           ((dst_roi.bottom - dst_roi.top) != (src_roi.bottom - src_roi.top));
    450 }
    451 
    452 void ResourceDefault::ResourceStateLog() {
    453   DLOGV_IF(kTagResources, "==== resource manager pipe state ====");
    454   uint32_t i;
    455   for (i = 0; i < num_pipe_; i++) {
    456     SourcePipe *src_pipe = &src_pipes_[i];
    457     DLOGV_IF(kTagResources, "index = %d, id = %x, hw_block = %d, owner = %s",
    458                  src_pipe->index, src_pipe->mdss_pipe_id, src_pipe->hw_block_id,
    459                  (src_pipe->owner == kPipeOwnerUserMode) ? "user mode" : "kernel mode");
    460   }
    461 }
    462 
    463 DisplayError ResourceDefault::SrcSplitConfig(DisplayResourceContext *display_resource_ctx,
    464                                         const LayerRect &src_rect, const LayerRect &dst_rect,
    465                                         HWLayerConfig *layer_config) {
    466   HWPipeInfo *left_pipe = &layer_config->left_pipe;
    467   HWPipeInfo *right_pipe = &layer_config->right_pipe;
    468   float src_width = src_rect.right - src_rect.left;
    469   float dst_width = dst_rect.right - dst_rect.left;
    470 
    471   // Layer cannot qualify for SrcSplit if source or destination width exceeds max pipe width.
    472   if ((src_width > hw_res_info_.max_pipe_width) || (dst_width > hw_res_info_.max_pipe_width)) {
    473     SplitRect(src_rect, dst_rect, &left_pipe->src_roi, &left_pipe->dst_roi, &right_pipe->src_roi,
    474               &right_pipe->dst_roi);
    475     left_pipe->valid = true;
    476     right_pipe->valid = true;
    477   } else {
    478     left_pipe->src_roi = src_rect;
    479     left_pipe->dst_roi = dst_rect;
    480     left_pipe->valid = true;
    481     right_pipe->Reset();
    482   }
    483 
    484   return kErrorNone;
    485 }
    486 
    487 DisplayError ResourceDefault::DisplaySplitConfig(DisplayResourceContext *display_resource_ctx,
    488                                             const LayerRect &src_rect, const LayerRect &dst_rect,
    489                                             HWLayerConfig *layer_config) {
    490   HWMixerAttributes &mixer_attributes = display_resource_ctx->mixer_attributes;
    491 
    492   // for display split case
    493   HWPipeInfo *left_pipe = &layer_config->left_pipe;
    494   HWPipeInfo *right_pipe = &layer_config->right_pipe;
    495   LayerRect scissor_left, scissor_right, dst_left, crop_left, crop_right, dst_right;
    496 
    497   scissor_left.right = FLOAT(mixer_attributes.split_left);
    498   scissor_left.bottom = FLOAT(mixer_attributes.height);
    499 
    500   scissor_right.left = FLOAT(mixer_attributes.split_left);
    501   scissor_right.top = 0.0f;
    502   scissor_right.right = FLOAT(mixer_attributes.width);
    503   scissor_right.bottom = FLOAT(mixer_attributes.height);
    504 
    505   crop_left = src_rect;
    506   dst_left = dst_rect;
    507   crop_right = crop_left;
    508   dst_right = dst_left;
    509 
    510   bool crop_left_valid = CalculateCropRects(scissor_left, &crop_left, &dst_left);
    511   bool crop_right_valid = false;
    512 
    513   if (IsValid(scissor_right)) {
    514     crop_right_valid = CalculateCropRects(scissor_right, &crop_right, &dst_right);
    515   }
    516 
    517   // Reset left_pipe and right_pipe to invalid by default
    518   left_pipe->Reset();
    519   right_pipe->Reset();
    520 
    521   if (crop_left_valid) {
    522     // assign left pipe
    523     left_pipe->src_roi = crop_left;
    524     left_pipe->dst_roi = dst_left;
    525     left_pipe->valid = true;
    526   }
    527 
    528   // assign right pipe if needed
    529   if (crop_right_valid) {
    530     right_pipe->src_roi = crop_right;
    531     right_pipe->dst_roi = dst_right;
    532     right_pipe->valid = true;
    533   }
    534 
    535   return kErrorNone;
    536 }
    537 
    538 DisplayError ResourceDefault::Config(DisplayResourceContext *display_resource_ctx,
    539                                 HWLayers *hw_layers) {
    540   HWLayersInfo &layer_info = hw_layers->info;
    541   DisplayError error = kErrorNone;
    542   const Layer &layer = layer_info.hw_layers.at(0);
    543 
    544   error = ValidateLayerParams(&layer);
    545   if (error != kErrorNone) {
    546     return error;
    547   }
    548 
    549   struct HWLayerConfig *layer_config = &hw_layers->config[0];
    550   HWPipeInfo &left_pipe = layer_config->left_pipe;
    551   HWPipeInfo &right_pipe = layer_config->right_pipe;
    552 
    553   LayerRect src_rect = layer.src_rect;
    554   LayerRect dst_rect = layer.dst_rect;
    555 
    556   error = ValidateDimensions(src_rect, dst_rect);
    557   if (error != kErrorNone) {
    558     return error;
    559   }
    560 
    561   BufferLayout layout = GetBufferLayout(layer.input_buffer.format);
    562   error = ValidateScaling(src_rect, dst_rect, false /*rotated90 */, layout,
    563                           false /* use_rotator_downscale */);
    564   if (error != kErrorNone) {
    565     return error;
    566   }
    567 
    568   if (hw_res_info_.is_src_split) {
    569     error = SrcSplitConfig(display_resource_ctx, src_rect, dst_rect, layer_config);
    570   } else {
    571     error = DisplaySplitConfig(display_resource_ctx, src_rect, dst_rect, layer_config);
    572   }
    573 
    574   if (error != kErrorNone) {
    575     return error;
    576   }
    577 
    578   error = AlignPipeConfig(&layer, &left_pipe, &right_pipe);
    579   if (error != kErrorNone) {
    580     return error;
    581   }
    582 
    583   // set z_order, left_pipe should always be valid
    584   left_pipe.z_order = 0;
    585 
    586   DLOGV_IF(kTagResources, "==== FB layer Config ====");
    587   Log(kTagResources, "input layer src_rect", layer.src_rect);
    588   Log(kTagResources, "input layer dst_rect", layer.dst_rect);
    589   Log(kTagResources, "cropped src_rect", src_rect);
    590   Log(kTagResources, "cropped dst_rect", dst_rect);
    591   Log(kTagResources, "left pipe src", layer_config->left_pipe.src_roi);
    592   Log(kTagResources, "left pipe dst", layer_config->left_pipe.dst_roi);
    593   if (right_pipe.valid) {
    594     right_pipe.z_order = 0;
    595     Log(kTagResources, "right pipe src", layer_config->right_pipe.src_roi);
    596     Log(kTagResources, "right pipe dst", layer_config->right_pipe.dst_roi);
    597   }
    598 
    599   return error;
    600 }
    601 
    602 bool ResourceDefault::CalculateCropRects(const LayerRect &scissor, LayerRect *crop,
    603                                          LayerRect *dst) {
    604   float &crop_left = crop->left;
    605   float &crop_top = crop->top;
    606   float &crop_right = crop->right;
    607   float &crop_bottom = crop->bottom;
    608   float crop_width = crop->right - crop->left;
    609   float crop_height = crop->bottom - crop->top;
    610 
    611   float &dst_left = dst->left;
    612   float &dst_top = dst->top;
    613   float &dst_right = dst->right;
    614   float &dst_bottom = dst->bottom;
    615   float dst_width = dst->right - dst->left;
    616   float dst_height = dst->bottom - dst->top;
    617 
    618   const float &sci_left = scissor.left;
    619   const float &sci_top = scissor.top;
    620   const float &sci_right = scissor.right;
    621   const float &sci_bottom = scissor.bottom;
    622 
    623   float left_cut_ratio = 0.0, right_cut_ratio = 0.0, top_cut_ratio = 0.0, bottom_cut_ratio = 0.0;
    624   bool need_cut = false;
    625 
    626   if (dst_left < sci_left) {
    627     left_cut_ratio = (sci_left - dst_left) / dst_width;
    628     dst_left = sci_left;
    629     need_cut = true;
    630   }
    631 
    632   if (dst_right > sci_right) {
    633     right_cut_ratio = (dst_right - sci_right) / dst_width;
    634     dst_right = sci_right;
    635     need_cut = true;
    636   }
    637 
    638   if (dst_top < sci_top) {
    639     top_cut_ratio = (sci_top - dst_top) / (dst_height);
    640     dst_top = sci_top;
    641     need_cut = true;
    642   }
    643 
    644   if (dst_bottom > sci_bottom) {
    645     bottom_cut_ratio = (dst_bottom - sci_bottom) / (dst_height);
    646     dst_bottom = sci_bottom;
    647     need_cut = true;
    648   }
    649 
    650   if (!need_cut)
    651     return true;
    652 
    653   crop_left += crop_width * left_cut_ratio;
    654   crop_top += crop_height * top_cut_ratio;
    655   crop_right -= crop_width * right_cut_ratio;
    656   crop_bottom -= crop_height * bottom_cut_ratio;
    657   Normalize(1, 1, crop);
    658   Normalize(1, 1, dst);
    659   if (IsValid(*crop) && IsValid(*dst))
    660     return true;
    661   else
    662     return false;
    663 }
    664 
    665 DisplayError ResourceDefault::ValidateLayerParams(const Layer *layer) {
    666   const LayerRect &src = layer->src_rect;
    667   const LayerRect &dst = layer->dst_rect;
    668   const LayerBuffer &input_buffer = layer->input_buffer;
    669 
    670   if (input_buffer.format == kFormatInvalid) {
    671     DLOGV_IF(kTagResources, "Invalid input buffer format %d", input_buffer.format);
    672     return kErrorNotSupported;
    673   }
    674 
    675   if (!IsValid(src) || !IsValid(dst)) {
    676     Log(kTagResources, "input layer src_rect", src);
    677     Log(kTagResources, "input layer dst_rect", dst);
    678     return kErrorNotSupported;
    679   }
    680 
    681   // Make sure source in integral only if it is a non secure layer.
    682   if (!input_buffer.flags.secure &&
    683       ((src.left - roundf(src.left) != 0.0f) ||
    684        (src.top - roundf(src.top) != 0.0f) ||
    685        (src.right - roundf(src.right) != 0.0f) ||
    686        (src.bottom - roundf(src.bottom) != 0.0f))) {
    687     DLOGV_IF(kTagResources, "Input ROI is not integral");
    688     return kErrorNotSupported;
    689   }
    690 
    691   return kErrorNone;
    692 }
    693 
    694 DisplayError ResourceDefault::ValidateDimensions(const LayerRect &crop, const LayerRect &dst) {
    695   if (!IsValid(crop)) {
    696     Log(kTagResources, "Invalid crop rect", crop);
    697     return kErrorNotSupported;
    698   }
    699 
    700   if (!IsValid(dst)) {
    701     Log(kTagResources, "Invalid dst rect", dst);
    702     return kErrorNotSupported;
    703   }
    704 
    705   float crop_width = crop.right - crop.left;
    706   float crop_height = crop.bottom - crop.top;
    707   float dst_width = dst.right - dst.left;
    708   float dst_height = dst.bottom - dst.top;
    709 
    710   if ((UINT32(crop_width - dst_width) == 1) || (UINT32(crop_height - dst_height) == 1)) {
    711     DLOGV_IF(kTagResources, "One pixel downscaling detected crop_w = %.0f, dst_w = %.0f, " \
    712              "crop_h = %.0f, dst_h = %.0f", crop_width, dst_width, crop_height, dst_height);
    713     return kErrorNotSupported;
    714   }
    715 
    716   return kErrorNone;
    717 }
    718 
    719 DisplayError ResourceDefault::ValidatePipeParams(HWPipeInfo *pipe_info, LayerBufferFormat format) {
    720   DisplayError error = kErrorNone;
    721 
    722   const LayerRect &src_rect = pipe_info->src_roi;
    723   const LayerRect &dst_rect = pipe_info->dst_roi;
    724 
    725   error = ValidateDimensions(src_rect, dst_rect);
    726   if (error != kErrorNone) {
    727     return error;
    728   }
    729 
    730   BufferLayout layout = GetBufferLayout(format);
    731   error = ValidateScaling(src_rect, dst_rect, false /* rotated90 */, layout,
    732                           false /* use_rotator_downscale */);
    733   if (error != kErrorNone) {
    734     return error;
    735   }
    736 
    737   return kErrorNone;
    738 }
    739 
    740 DisplayError ResourceDefault::ValidateScaling(const LayerRect &crop, const LayerRect &dst,
    741                                               bool rotate90, BufferLayout layout,
    742                                               bool use_rotator_downscale) {
    743   DisplayError error = kErrorNone;
    744 
    745   float scale_x = 1.0f;
    746   float scale_y = 1.0f;
    747 
    748   error = GetScaleFactor(crop, dst, &scale_x, &scale_y);
    749   if (error != kErrorNone) {
    750     return error;
    751   }
    752 
    753   error = ValidateDownScaling(scale_x, scale_y, (layout != kLinear));
    754   if (error != kErrorNone) {
    755     return error;
    756   }
    757 
    758   error = ValidateUpScaling(scale_x, scale_y);
    759   if (error != kErrorNone) {
    760     return error;
    761   }
    762 
    763   return kErrorNone;
    764 }
    765 
    766 DisplayError ResourceDefault::ValidateDownScaling(float scale_x, float scale_y, bool ubwc_tiled) {
    767   if ((UINT32(scale_x) > 1) || (UINT32(scale_y) > 1)) {
    768     float max_scale_down = FLOAT(hw_res_info_.max_scale_down);
    769 
    770     // MDP H/W cannot apply decimation on UBWC tiled framebuffer
    771     if (!ubwc_tiled && hw_res_info_.has_decimation) {
    772       max_scale_down *= FLOAT(kMaxDecimationDownScaleRatio);
    773     }
    774 
    775     if (scale_x > max_scale_down || scale_y > max_scale_down) {
    776       DLOGV_IF(kTagResources,
    777                "Scaling down is over the limit: scale_x = %.0f, scale_y = %.0f, " \
    778                "has_deci = %d", scale_x, scale_y, hw_res_info_.has_decimation);
    779       return kErrorNotSupported;
    780     }
    781   }
    782 
    783   DLOGV_IF(kTagResources, "scale_x = %.4f, scale_y = %.4f", scale_x, scale_y);
    784 
    785   return kErrorNone;
    786 }
    787 
    788 DisplayError ResourceDefault::ValidateUpScaling(float scale_x, float scale_y) {
    789   float max_scale_up = FLOAT(hw_res_info_.max_scale_up);
    790 
    791   if (UINT32(scale_x) < 1 && scale_x > 0.0f) {
    792     if ((1.0f / scale_x) > max_scale_up) {
    793       DLOGV_IF(kTagResources, "Scaling up is over limit scale_x = %f", 1.0f / scale_x);
    794       return kErrorNotSupported;
    795     }
    796   }
    797 
    798   if (UINT32(scale_y) < 1 && scale_y > 0.0f) {
    799     if ((1.0f / scale_y) > max_scale_up) {
    800       DLOGV_IF(kTagResources, "Scaling up is over limit scale_y = %f", 1.0f / scale_y);
    801       return kErrorNotSupported;
    802     }
    803   }
    804 
    805   DLOGV_IF(kTagResources, "scale_x = %.4f, scale_y = %.4f", scale_x, scale_y);
    806 
    807   return kErrorNone;
    808 }
    809 
    810 DisplayError ResourceDefault::GetScaleFactor(const LayerRect &crop, const LayerRect &dst,
    811                                         float *scale_x, float *scale_y) {
    812   float crop_width = crop.right - crop.left;
    813   float crop_height = crop.bottom - crop.top;
    814   float dst_width = dst.right - dst.left;
    815   float dst_height = dst.bottom - dst.top;
    816 
    817   *scale_x = crop_width / dst_width;
    818   *scale_y = crop_height / dst_height;
    819 
    820   return kErrorNone;
    821 }
    822 
    823 DisplayError ResourceDefault::SetDecimationFactor(HWPipeInfo *pipe) {
    824   float src_h = pipe->src_roi.bottom - pipe->src_roi.top;
    825   float dst_h = pipe->dst_roi.bottom - pipe->dst_roi.top;
    826   float down_scale_h = src_h / dst_h;
    827 
    828   float src_w = pipe->src_roi.right - pipe->src_roi.left;
    829   float dst_w = pipe->dst_roi.right - pipe->dst_roi.left;
    830   float down_scale_w = src_w / dst_w;
    831 
    832   pipe->horizontal_decimation = 0;
    833   pipe->vertical_decimation = 0;
    834 
    835   if (CalculateDecimation(down_scale_w, &pipe->horizontal_decimation) != kErrorNone) {
    836     return kErrorNotSupported;
    837   }
    838 
    839   if (CalculateDecimation(down_scale_h, &pipe->vertical_decimation) != kErrorNone) {
    840     return kErrorNotSupported;
    841   }
    842 
    843   DLOGI_IF(kTagResources, "horizontal_decimation %d, vertical_decimation %d",
    844            pipe->horizontal_decimation, pipe->vertical_decimation);
    845 
    846   return kErrorNone;
    847 }
    848 
    849 void ResourceDefault::SplitRect(const LayerRect &src_rect, const LayerRect &dst_rect,
    850                            LayerRect *src_left, LayerRect *dst_left, LayerRect *src_right,
    851                            LayerRect *dst_right) {
    852   // Split rectangle horizontally and evenly into two.
    853   float src_width = src_rect.right - src_rect.left;
    854   float dst_width = dst_rect.right - dst_rect.left;
    855   float src_width_ori = src_width;
    856   src_width = ROUND_UP_ALIGN_DOWN(src_width / 2, 1);
    857   dst_width = ROUND_UP_ALIGN_DOWN(dst_width * src_width / src_width_ori, 1);
    858 
    859   src_left->left = src_rect.left;
    860   src_left->right = src_rect.left + src_width;
    861   src_right->left = src_left->right;
    862   src_right->right = src_rect.right;
    863 
    864   src_left->top = src_rect.top;
    865   src_left->bottom = src_rect.bottom;
    866   src_right->top = src_rect.top;
    867   src_right->bottom = src_rect.bottom;
    868 
    869   dst_left->top = dst_rect.top;
    870   dst_left->bottom = dst_rect.bottom;
    871   dst_right->top = dst_rect.top;
    872   dst_right->bottom = dst_rect.bottom;
    873 
    874   dst_left->left = dst_rect.left;
    875   dst_left->right = dst_rect.left + dst_width;
    876   dst_right->left = dst_left->right;
    877   dst_right->right = dst_rect.right;
    878 }
    879 
    880 DisplayError ResourceDefault::AlignPipeConfig(const Layer *layer, HWPipeInfo *left_pipe,
    881                                               HWPipeInfo *right_pipe) {
    882   DisplayError error = kErrorNone;
    883   if (!left_pipe->valid) {
    884     DLOGE_IF(kTagResources, "left_pipe should not be invalid");
    885     return kErrorNotSupported;
    886   }
    887 
    888   error = ValidatePipeParams(left_pipe, layer->input_buffer.format);
    889   if (error != kErrorNone) {
    890     goto PipeConfigExit;
    891   }
    892 
    893   if (right_pipe->valid) {
    894     // Make sure the  left and right ROI are conjunct
    895     right_pipe->src_roi.left = left_pipe->src_roi.right;
    896     right_pipe->dst_roi.left = left_pipe->dst_roi.right;
    897     error = ValidatePipeParams(right_pipe, layer->input_buffer.format);
    898   }
    899 
    900 PipeConfigExit:
    901   if (error != kErrorNone) {
    902     DLOGV_IF(kTagResources, "AlignPipeConfig failed");
    903   }
    904   return error;
    905 }
    906 
    907 DisplayError ResourceDefault::CalculateDecimation(float downscale, uint8_t *decimation) {
    908   float max_down_scale = FLOAT(hw_res_info_.max_scale_down);
    909 
    910   if (downscale <= max_down_scale) {
    911     *decimation = 0;
    912     return kErrorNone;
    913   } else if (!hw_res_info_.has_decimation) {
    914     DLOGE("Downscaling exceeds the maximum MDP downscale limit but decimation not enabled");
    915     return kErrorNotSupported;
    916   }
    917 
    918   // Decimation is the remaining downscale factor after doing max SDE downscale.
    919   // In SDE, decimation is supported in powers of 2.
    920   // For ex: If a pipe needs downscale of 8 but max_down_scale is 4
    921   // So decimation = powf(2.0, ceilf(log2f(8 / 4))) = powf(2.0, 1.0) = 2
    922   *decimation = UINT8(ceilf(log2f(downscale / max_down_scale)));
    923   return kErrorNone;
    924 }
    925 
    926 DisplayError ResourceDefault::ValidateCursorConfig(Handle display_ctx, const Layer *layer,
    927                                                    bool is_top) {
    928   return kErrorNotSupported;
    929 }
    930 
    931 DisplayError ResourceDefault::ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers,
    932                                                      int x, int y) {
    933   return kErrorNotSupported;
    934 }
    935 
    936 DisplayError ResourceDefault::SetMaxBandwidthMode(HWBwModes mode) {
    937   return kErrorNotSupported;
    938 }
    939 
    940 DisplayError ResourceDefault::GetScaleLutConfig(HWScaleLutInfo *lut_info) {
    941   return kErrorNone;
    942 }
    943 
    944 DisplayError ResourceDefault::SetDetailEnhancerData(Handle display_ctx,
    945                                                     const DisplayDetailEnhancerData &de_data) {
    946   return kErrorNotSupported;
    947 }
    948 
    949 }  // namespace sdm
    950