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