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