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