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
38namespace sdm {
39
40DisplayError 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
102DisplayError ResourceDefault::Deinit() {
103  return kErrorNone;
104}
105
106DisplayError 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
151DisplayError 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
163DisplayError 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
178DisplayError ResourceDefault::Start(Handle display_ctx) {
179  locker_.Lock();
180
181  return kErrorNone;
182}
183
184DisplayError ResourceDefault::Stop(Handle display_ctx) {
185  locker_.Unlock();
186
187  return kErrorNone;
188}
189
190DisplayError 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
288CleanupOnError:
289  DLOGV_IF(kTagResources, "Resource reserving failed! hw_block = %d", hw_block_id);
290
291  return kErrorResources;
292}
293
294DisplayError ResourceDefault::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
295  SCOPE_LOCK(locker_);
296
297  return kErrorNone;
298}
299
300DisplayError 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
326void 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
341DisplayError ResourceDefault::SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) {
342  SCOPE_LOCK(locker_);
343
344  return kErrorNone;
345}
346
347uint32_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
365uint32_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
388uint32_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
407bool 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
415void 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
426DisplayError 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
450DisplayError 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
501DisplayError 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
565bool 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
628DisplayError 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
657DisplayError 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
682DisplayError 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
702DisplayError 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
728DisplayError 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
750DisplayError 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
772DisplayError 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
785DisplayError 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
811void 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
842DisplayError 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
863PipeConfigExit:
864  if (error != kErrorNone) {
865    DLOGV_IF(kTagResources, "AlignPipeConfig failed");
866  }
867  return error;
868}
869
870DisplayError 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
889DisplayError ResourceDefault::ValidateCursorConfig(Handle display_ctx, const Layer *layer,
890                                                   bool is_top) {
891  return kErrorNotSupported;
892}
893
894DisplayError ResourceDefault::ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers,
895                                                     int x, int y) {
896  return kErrorNotSupported;
897}
898
899DisplayError ResourceDefault::SetMaxBandwidthMode(HWBwModes mode) {
900  return kErrorNotSupported;
901}
902
903DisplayError ResourceDefault::GetScaleLutConfig(HWScaleLutInfo *lut_info) {
904  return kErrorNone;
905}
906
907DisplayError ResourceDefault::SetDetailEnhancerData(Handle display_ctx,
908                                                    const DisplayDetailEnhancerData &de_data) {
909  return kErrorNotSupported;
910}
911
912}  // namespace sdm
913