• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Init(const HWResourceInfo & hw_res_info)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 
Deinit()102 DisplayError ResourceDefault::Deinit() {
103   return kErrorNone;
104 }
105 
RegisterDisplay(DisplayType type,const HWDisplayAttributes & display_attributes,const HWPanelInfo & hw_panel_info,const HWMixerAttributes & mixer_attributes,Handle * display_ctx)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 
UnregisterDisplay(Handle display_ctx)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 
ReconfigureDisplay(Handle display_ctx,const HWDisplayAttributes & display_attributes,const HWPanelInfo & hw_panel_info,const HWMixerAttributes & mixer_attributes)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 
Start(Handle display_ctx)178 DisplayError ResourceDefault::Start(Handle display_ctx) {
179   locker_.Lock();
180 
181   return kErrorNone;
182 }
183 
Stop(Handle display_ctx)184 DisplayError ResourceDefault::Stop(Handle display_ctx) {
185   locker_.Unlock();
186 
187   return kErrorNone;
188 }
189 
Acquire(Handle display_ctx,HWLayers * hw_layers)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 
PostPrepare(Handle display_ctx,HWLayers * hw_layers)294 DisplayError ResourceDefault::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
295   SCOPE_LOCK(locker_);
296 
297   return kErrorNone;
298 }
299 
PostCommit(Handle display_ctx,HWLayers * hw_layers)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 
Purge(Handle display_ctx)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 
SetMaxMixerStages(Handle display_ctx,uint32_t max_mixer_stages)341 DisplayError ResourceDefault::SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) {
342   SCOPE_LOCK(locker_);
343 
344   return kErrorNone;
345 }
346 
SearchPipe(HWBlockType hw_block_id,SourcePipe * src_pipes,uint32_t num_pipe)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 
NextPipe(PipeType type,HWBlockType hw_block_id)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 
GetPipe(HWBlockType hw_block_id,bool need_scale)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 
IsScalingNeeded(const HWPipeInfo * pipe_info)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 
ResourceStateLog()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 
SrcSplitConfig(DisplayResourceContext * display_resource_ctx,const LayerRect & src_rect,const LayerRect & dst_rect,HWLayerConfig * layer_config)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 
DisplaySplitConfig(DisplayResourceContext * display_resource_ctx,const LayerRect & src_rect,const LayerRect & dst_rect,HWLayerConfig * layer_config)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 
Config(DisplayResourceContext * display_resource_ctx,HWLayers * hw_layers)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 
CalculateCropRects(const LayerRect & scissor,LayerRect * crop,LayerRect * dst)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 
ValidateLayerParams(const Layer * layer)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 
ValidateDimensions(const LayerRect & crop,const LayerRect & dst)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 
ValidatePipeParams(HWPipeInfo * pipe_info,bool ubwc_tiled)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 
ValidateScaling(const LayerRect & crop,const LayerRect & dst,bool rotate90,bool ubwc_tiled,bool use_rotator_downscale)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 
ValidateDownScaling(float scale_x,float scale_y,bool ubwc_tiled)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 
ValidateUpScaling(float scale_x,float scale_y)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 
GetScaleFactor(const LayerRect & crop,const LayerRect & dst,float * scale_x,float * scale_y)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 
SetDecimationFactor(HWPipeInfo * pipe)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 
SplitRect(const LayerRect & src_rect,const LayerRect & dst_rect,LayerRect * src_left,LayerRect * dst_left,LayerRect * src_right,LayerRect * dst_right)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 
AlignPipeConfig(const Layer * layer,HWPipeInfo * left_pipe,HWPipeInfo * right_pipe)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 
CalculateDecimation(float downscale,uint8_t * decimation)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 
ValidateCursorConfig(Handle display_ctx,const Layer * layer,bool is_top)889 DisplayError ResourceDefault::ValidateCursorConfig(Handle display_ctx, const Layer *layer,
890                                                    bool is_top) {
891   return kErrorNotSupported;
892 }
893 
ValidateCursorPosition(Handle display_ctx,HWLayers * hw_layers,int x,int y)894 DisplayError ResourceDefault::ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers,
895                                                      int x, int y) {
896   return kErrorNotSupported;
897 }
898 
SetMaxBandwidthMode(HWBwModes mode)899 DisplayError ResourceDefault::SetMaxBandwidthMode(HWBwModes mode) {
900   return kErrorNotSupported;
901 }
902 
GetScaleLutConfig(HWScaleLutInfo * lut_info)903 DisplayError ResourceDefault::GetScaleLutConfig(HWScaleLutInfo *lut_info) {
904   return kErrorNone;
905 }
906 
SetDetailEnhancerData(Handle display_ctx,const DisplayDetailEnhancerData & de_data)907 DisplayError ResourceDefault::SetDetailEnhancerData(Handle display_ctx,
908                                                     const DisplayDetailEnhancerData &de_data) {
909   return kErrorNotSupported;
910 }
911 
912 }  // namespace sdm
913