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