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