1 /* 2 * Copyright (c) 2014 - 2017, 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 <utils/constants.h> 26 #include <utils/debug.h> 27 #include <core/buffer_allocator.h> 28 29 #include "comp_manager.h" 30 #include "strategy.h" 31 32 #define __CLASS__ "CompManager" 33 34 namespace sdm { 35 36 static bool NeedsScaledComposition(const DisplayConfigVariableInfo &fb_config, 37 const HWMixerAttributes &mixer_attributes) { 38 return ((fb_config.x_pixels != mixer_attributes.width) || 39 (fb_config.y_pixels != mixer_attributes.height)); 40 } 41 42 DisplayError CompManager::Init(const HWResourceInfo &hw_res_info, 43 ExtensionInterface *extension_intf, 44 BufferAllocator *buffer_allocator, 45 BufferSyncHandler *buffer_sync_handler, 46 SocketHandler *socket_handler) { 47 SCOPE_LOCK(locker_); 48 49 DisplayError error = kErrorNone; 50 51 if (extension_intf) { 52 error = extension_intf->CreateResourceExtn(hw_res_info, buffer_allocator, buffer_sync_handler, 53 &resource_intf_); 54 extension_intf->CreateDppsControlExtn(&dpps_ctrl_intf_, socket_handler); 55 } else { 56 error = ResourceDefault::CreateResourceDefault(hw_res_info, &resource_intf_); 57 } 58 59 if (error != kErrorNone) { 60 if (extension_intf) { 61 extension_intf->DestroyDppsControlExtn(dpps_ctrl_intf_); 62 } 63 return error; 64 } 65 66 hw_res_info_ = hw_res_info; 67 buffer_allocator_ = buffer_allocator; 68 extension_intf_ = extension_intf; 69 70 return error; 71 } 72 73 DisplayError CompManager::Deinit() { 74 SCOPE_LOCK(locker_); 75 76 if (extension_intf_) { 77 extension_intf_->DestroyResourceExtn(resource_intf_); 78 extension_intf_->DestroyDppsControlExtn(dpps_ctrl_intf_); 79 } else { 80 ResourceDefault::DestroyResourceDefault(resource_intf_); 81 } 82 83 return kErrorNone; 84 } 85 86 DisplayError CompManager::RegisterDisplay(DisplayType type, 87 const HWDisplayAttributes &display_attributes, 88 const HWPanelInfo &hw_panel_info, 89 const HWMixerAttributes &mixer_attributes, 90 const DisplayConfigVariableInfo &fb_config, 91 Handle *display_ctx) { 92 SCOPE_LOCK(locker_); 93 94 DisplayError error = kErrorNone; 95 96 DisplayCompositionContext *display_comp_ctx = new DisplayCompositionContext(); 97 if (!display_comp_ctx) { 98 return kErrorMemory; 99 } 100 101 Strategy *&strategy = display_comp_ctx->strategy; 102 strategy = new Strategy(extension_intf_, buffer_allocator_, type, hw_res_info_, hw_panel_info, 103 mixer_attributes, display_attributes, fb_config); 104 if (!strategy) { 105 DLOGE("Unable to create strategy"); 106 delete display_comp_ctx; 107 return kErrorMemory; 108 } 109 110 error = strategy->Init(); 111 if (error != kErrorNone) { 112 delete strategy; 113 delete display_comp_ctx; 114 return error; 115 } 116 117 error = resource_intf_->RegisterDisplay(type, display_attributes, hw_panel_info, mixer_attributes, 118 &display_comp_ctx->display_resource_ctx); 119 if (error != kErrorNone) { 120 strategy->Deinit(); 121 delete strategy; 122 delete display_comp_ctx; 123 display_comp_ctx = NULL; 124 return error; 125 } 126 127 registered_displays_[type] = 1; 128 display_comp_ctx->is_primary_panel = hw_panel_info.is_primary_panel; 129 display_comp_ctx->display_type = type; 130 display_comp_ctx->fb_config = fb_config; 131 *display_ctx = display_comp_ctx; 132 // New non-primary display device has been added, so move the composition mode to safe mode until 133 // resources for the added display is configured properly. 134 if (!display_comp_ctx->is_primary_panel) { 135 safe_mode_ = true; 136 max_sde_ext_layers_ = UINT32(Debug::GetExtMaxlayers()); 137 } 138 139 display_comp_ctx->scaled_composition = NeedsScaledComposition(fb_config, mixer_attributes); 140 DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \ 141 "display type %d", registered_displays_.to_ulong(), configured_displays_.to_ulong(), 142 display_comp_ctx->display_type); 143 144 return kErrorNone; 145 } 146 147 DisplayError CompManager::UnregisterDisplay(Handle display_ctx) { 148 SCOPE_LOCK(locker_); 149 150 DisplayCompositionContext *display_comp_ctx = 151 reinterpret_cast<DisplayCompositionContext *>(display_ctx); 152 153 if (!display_comp_ctx) { 154 return kErrorParameters; 155 } 156 157 resource_intf_->UnregisterDisplay(display_comp_ctx->display_resource_ctx); 158 159 Strategy *&strategy = display_comp_ctx->strategy; 160 strategy->Deinit(); 161 delete strategy; 162 163 registered_displays_[display_comp_ctx->display_type] = 0; 164 configured_displays_[display_comp_ctx->display_type] = 0; 165 166 if (display_comp_ctx->display_type == kHDMI) { 167 max_layers_ = kMaxSDELayers; 168 } 169 170 DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \ 171 "display type %d", registered_displays_.to_ulong(), configured_displays_.to_ulong(), 172 display_comp_ctx->display_type); 173 174 delete display_comp_ctx; 175 display_comp_ctx = NULL; 176 return kErrorNone; 177 } 178 179 DisplayError CompManager::ReconfigureDisplay(Handle comp_handle, 180 const HWDisplayAttributes &display_attributes, 181 const HWPanelInfo &hw_panel_info, 182 const HWMixerAttributes &mixer_attributes, 183 const DisplayConfigVariableInfo &fb_config) { 184 SCOPE_LOCK(locker_); 185 186 DisplayError error = kErrorNone; 187 DisplayCompositionContext *display_comp_ctx = 188 reinterpret_cast<DisplayCompositionContext *>(comp_handle); 189 190 error = resource_intf_->ReconfigureDisplay(display_comp_ctx->display_resource_ctx, 191 display_attributes, hw_panel_info, mixer_attributes); 192 if (error != kErrorNone) { 193 return error; 194 } 195 196 if (display_comp_ctx->strategy) { 197 error = display_comp_ctx->strategy->Reconfigure(hw_panel_info, display_attributes, 198 mixer_attributes, fb_config); 199 if (error != kErrorNone) { 200 DLOGE("Unable to Reconfigure strategy."); 201 display_comp_ctx->strategy->Deinit(); 202 delete display_comp_ctx->strategy; 203 display_comp_ctx->strategy = NULL; 204 return error; 205 } 206 } 207 208 // For HDMI S3D mode, set max_layers_ to 0 so that primary display would fall back 209 // to GPU composition to release pipes for HDMI. 210 if (display_comp_ctx->display_type == kHDMI) { 211 if (hw_panel_info.s3d_mode != kS3DModeNone) { 212 max_layers_ = 0; 213 } else { 214 max_layers_ = kMaxSDELayers; 215 } 216 } 217 218 display_comp_ctx->scaled_composition = NeedsScaledComposition(fb_config, mixer_attributes); 219 // Update new resolution. 220 display_comp_ctx->fb_config = fb_config; 221 222 return error; 223 } 224 225 void CompManager::PrepareStrategyConstraints(Handle comp_handle, HWLayers *hw_layers) { 226 DisplayCompositionContext *display_comp_ctx = 227 reinterpret_cast<DisplayCompositionContext *>(comp_handle); 228 StrategyConstraints *constraints = &display_comp_ctx->constraints; 229 230 constraints->safe_mode = safe_mode_; 231 constraints->use_cursor = false; 232 constraints->max_layers = max_layers_; 233 234 // Limit 2 layer SDE Comp if its not a Primary Display. 235 // Safe mode is the policy for External display on a low end device. 236 if (!display_comp_ctx->is_primary_panel) { 237 bool low_end_hw = ((hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe + 238 hw_res_info_.num_dma_pipe) <= kSafeModeThreshold); 239 constraints->max_layers = max_sde_ext_layers_; 240 constraints->safe_mode = (low_end_hw && !hw_res_info_.separate_rotator) ? true : safe_mode_; 241 } 242 243 // If a strategy fails after successfully allocating resources, then set safe mode 244 if (display_comp_ctx->remaining_strategies != display_comp_ctx->max_strategies) { 245 constraints->safe_mode = true; 246 } 247 248 // Set use_cursor constraint to Strategy 249 constraints->use_cursor = display_comp_ctx->valid_cursor; 250 251 // TODO(user): App layer count will change for hybrid composition 252 uint32_t app_layer_count = UINT32(hw_layers->info.stack->layers.size()) - 1; 253 if (display_comp_ctx->idle_fallback || display_comp_ctx->thermal_fallback_) { 254 // Handle the idle timeout by falling back 255 constraints->safe_mode = true; 256 } 257 258 // Avoid safe mode, if there is only one app layer. 259 if (app_layer_count == 1) { 260 constraints->safe_mode = false; 261 } 262 } 263 264 void CompManager::PrePrepare(Handle display_ctx, HWLayers *hw_layers) { 265 SCOPE_LOCK(locker_); 266 DisplayCompositionContext *display_comp_ctx = 267 reinterpret_cast<DisplayCompositionContext *>(display_ctx); 268 display_comp_ctx->valid_cursor = SupportLayerAsCursor(display_comp_ctx, hw_layers); 269 270 // pu constraints 271 display_comp_ctx->pu_constraints.enable_cursor_pu = display_comp_ctx->valid_cursor; 272 273 display_comp_ctx->strategy->Start(&hw_layers->info, &display_comp_ctx->max_strategies, 274 display_comp_ctx->pu_constraints); 275 display_comp_ctx->remaining_strategies = display_comp_ctx->max_strategies; 276 } 277 278 DisplayError CompManager::Prepare(Handle display_ctx, HWLayers *hw_layers) { 279 SCOPE_LOCK(locker_); 280 281 DisplayCompositionContext *display_comp_ctx = 282 reinterpret_cast<DisplayCompositionContext *>(display_ctx); 283 Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx; 284 285 DisplayError error = kErrorUndefined; 286 287 PrepareStrategyConstraints(display_ctx, hw_layers); 288 289 // Select a composition strategy, and try to allocate resources for it. 290 resource_intf_->Start(display_resource_ctx); 291 292 bool exit = false; 293 uint32_t &count = display_comp_ctx->remaining_strategies; 294 for (; !exit && count > 0; count--) { 295 error = display_comp_ctx->strategy->GetNextStrategy(&display_comp_ctx->constraints); 296 if (error != kErrorNone) { 297 // Composition strategies exhausted. Resource Manager could not allocate resources even for 298 // GPU composition. This will never happen. 299 exit = true; 300 } 301 302 if (!exit) { 303 error = resource_intf_->Prepare(display_resource_ctx, hw_layers); 304 // Exit if successfully prepared resource, else try next strategy. 305 exit = (error == kErrorNone); 306 } 307 } 308 309 if (error != kErrorNone) { 310 resource_intf_->Stop(display_resource_ctx, hw_layers); 311 DLOGE("Composition strategies exhausted for display = %d", display_comp_ctx->display_type); 312 return error; 313 } 314 315 error = resource_intf_->Stop(display_resource_ctx, hw_layers); 316 317 return error; 318 } 319 320 DisplayError CompManager::PostPrepare(Handle display_ctx, HWLayers *hw_layers) { 321 SCOPE_LOCK(locker_); 322 DisplayCompositionContext *display_comp_ctx = 323 reinterpret_cast<DisplayCompositionContext *>(display_ctx); 324 Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx; 325 326 DisplayError error = kErrorNone; 327 error = resource_intf_->PostPrepare(display_resource_ctx, hw_layers); 328 if (error != kErrorNone) { 329 return error; 330 } 331 332 display_comp_ctx->strategy->Stop(); 333 334 return kErrorNone; 335 } 336 337 DisplayError CompManager::Commit(Handle display_ctx, HWLayers *hw_layers) { 338 SCOPE_LOCK(locker_); 339 340 DisplayCompositionContext *display_comp_ctx = 341 reinterpret_cast<DisplayCompositionContext *>(display_ctx); 342 343 return resource_intf_->Commit(display_comp_ctx->display_resource_ctx, hw_layers); 344 } 345 346 DisplayError CompManager::ReConfigure(Handle display_ctx, HWLayers *hw_layers) { 347 SCOPE_LOCK(locker_); 348 349 DisplayCompositionContext *display_comp_ctx = 350 reinterpret_cast<DisplayCompositionContext *>(display_ctx); 351 Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx; 352 353 DisplayError error = kErrorUndefined; 354 resource_intf_->Start(display_resource_ctx); 355 error = resource_intf_->Prepare(display_resource_ctx, hw_layers); 356 357 if (error != kErrorNone) { 358 DLOGE("Reconfigure failed for display = %d", display_comp_ctx->display_type); 359 } 360 361 resource_intf_->Stop(display_resource_ctx, hw_layers); 362 if (error != kErrorNone) { 363 error = resource_intf_->PostPrepare(display_resource_ctx, hw_layers); 364 } 365 366 return error; 367 } 368 369 DisplayError CompManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) { 370 SCOPE_LOCK(locker_); 371 372 DisplayError error = kErrorNone; 373 DisplayCompositionContext *display_comp_ctx = 374 reinterpret_cast<DisplayCompositionContext *>(display_ctx); 375 configured_displays_[display_comp_ctx->display_type] = 1; 376 if (configured_displays_ == registered_displays_) { 377 safe_mode_ = false; 378 } 379 380 error = resource_intf_->PostCommit(display_comp_ctx->display_resource_ctx, hw_layers); 381 if (error != kErrorNone) { 382 return error; 383 } 384 385 display_comp_ctx->idle_fallback = false; 386 387 DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \ 388 "display type %d", registered_displays_, configured_displays_, 389 display_comp_ctx->display_type); 390 391 return kErrorNone; 392 } 393 394 void CompManager::Purge(Handle display_ctx) { 395 SCOPE_LOCK(locker_); 396 397 DisplayCompositionContext *display_comp_ctx = 398 reinterpret_cast<DisplayCompositionContext *>(display_ctx); 399 400 resource_intf_->Purge(display_comp_ctx->display_resource_ctx); 401 402 display_comp_ctx->strategy->Purge(); 403 } 404 405 DisplayError CompManager::SetIdleTimeoutMs(Handle display_ctx, uint32_t active_ms) { 406 SCOPE_LOCK(locker_); 407 408 DisplayCompositionContext *display_comp_ctx = 409 reinterpret_cast<DisplayCompositionContext *>(display_ctx); 410 411 return display_comp_ctx->strategy->SetIdleTimeoutMs(active_ms); 412 } 413 414 void CompManager::ProcessIdleTimeout(Handle display_ctx) { 415 SCOPE_LOCK(locker_); 416 417 DisplayCompositionContext *display_comp_ctx = 418 reinterpret_cast<DisplayCompositionContext *>(display_ctx); 419 420 if (!display_comp_ctx) { 421 return; 422 } 423 424 display_comp_ctx->idle_fallback = true; 425 } 426 427 void CompManager::ProcessThermalEvent(Handle display_ctx, int64_t thermal_level) { 428 SCOPE_LOCK(locker_); 429 430 DisplayCompositionContext *display_comp_ctx = 431 reinterpret_cast<DisplayCompositionContext *>(display_ctx); 432 433 if (thermal_level >= kMaxThermalLevel) { 434 display_comp_ctx->thermal_fallback_ = true; 435 } else { 436 display_comp_ctx->thermal_fallback_ = false; 437 } 438 } 439 440 void CompManager::ProcessIdlePowerCollapse(Handle display_ctx) { 441 SCOPE_LOCK(locker_); 442 443 DisplayCompositionContext *display_comp_ctx = 444 reinterpret_cast<DisplayCompositionContext *>(display_ctx); 445 446 if (display_comp_ctx) { 447 resource_intf_->Perform(ResourceInterface::kCmdResetScalarLUT, 448 display_comp_ctx->display_resource_ctx); 449 } 450 } 451 452 DisplayError CompManager::SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) { 453 SCOPE_LOCK(locker_); 454 455 DisplayError error = kErrorNone; 456 DisplayCompositionContext *display_comp_ctx = 457 reinterpret_cast<DisplayCompositionContext *>(display_ctx); 458 459 if (display_comp_ctx) { 460 error = resource_intf_->SetMaxMixerStages(display_comp_ctx->display_resource_ctx, 461 max_mixer_stages); 462 } 463 464 return error; 465 } 466 467 void CompManager::ControlPartialUpdate(Handle display_ctx, bool enable) { 468 SCOPE_LOCK(locker_); 469 470 DisplayCompositionContext *display_comp_ctx = 471 reinterpret_cast<DisplayCompositionContext *>(display_ctx); 472 display_comp_ctx->pu_constraints.enable = enable; 473 } 474 475 void CompManager::AppendDump(char *buffer, uint32_t length) { 476 SCOPE_LOCK(locker_); 477 } 478 479 DisplayError CompManager::ValidateScaling(const LayerRect &crop, const LayerRect &dst, 480 bool rotate90) { 481 BufferLayout layout = Debug::IsUbwcTiledFrameBuffer() ? kUBWC : kLinear; 482 return resource_intf_->ValidateScaling(crop, dst, rotate90, layout, true); 483 } 484 485 DisplayError CompManager::ValidateAndSetCursorPosition(Handle display_ctx, HWLayers *hw_layers, 486 int x, int y) { 487 DisplayCompositionContext *display_comp_ctx = 488 reinterpret_cast<DisplayCompositionContext *>(display_ctx); 489 Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx; 490 return resource_intf_->ValidateAndSetCursorPosition(display_resource_ctx, hw_layers, x, y, 491 &display_comp_ctx->fb_config); 492 } 493 494 bool CompManager::SupportLayerAsCursor(Handle comp_handle, HWLayers *hw_layers) { 495 DisplayCompositionContext *display_comp_ctx = 496 reinterpret_cast<DisplayCompositionContext *>(comp_handle); 497 Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx; 498 LayerStack *layer_stack = hw_layers->info.stack; 499 bool supported = false; 500 int32_t gpu_index = -1; 501 502 // HW Cursor cannot be used, if Display configuration needs scaled composition. 503 if (display_comp_ctx->scaled_composition || !layer_stack->flags.cursor_present) { 504 return supported; 505 } 506 507 for (int32_t i = INT32(layer_stack->layers.size() - 1); i >= 0; i--) { 508 Layer *layer = layer_stack->layers.at(UINT32(i)); 509 if (layer->composition == kCompositionGPUTarget) { 510 gpu_index = i; 511 break; 512 } 513 } 514 if (gpu_index <= 0) { 515 return supported; 516 } 517 Layer *cursor_layer = layer_stack->layers.at(UINT32(gpu_index) - 1); 518 if (cursor_layer->flags.cursor && !cursor_layer->flags.skip && 519 resource_intf_->ValidateCursorConfig(display_resource_ctx, 520 cursor_layer, true) == kErrorNone) { 521 supported = true; 522 } 523 524 return supported; 525 } 526 527 DisplayError CompManager::SetMaxBandwidthMode(HWBwModes mode) { 528 if ((hw_res_info_.has_dyn_bw_support == false) || (mode >= kBwModeMax)) { 529 return kErrorNotSupported; 530 } 531 532 return resource_intf_->SetMaxBandwidthMode(mode); 533 } 534 535 DisplayError CompManager::GetScaleLutConfig(HWScaleLutInfo *lut_info) { 536 return resource_intf_->GetScaleLutConfig(lut_info); 537 } 538 539 DisplayError CompManager::SetDetailEnhancerData(Handle display_ctx, 540 const DisplayDetailEnhancerData &de_data) { 541 SCOPE_LOCK(locker_); 542 543 DisplayCompositionContext *display_comp_ctx = 544 reinterpret_cast<DisplayCompositionContext *>(display_ctx); 545 546 return resource_intf_->SetDetailEnhancerData(display_comp_ctx->display_resource_ctx, de_data); 547 } 548 549 DisplayError CompManager::SetCompositionState(Handle display_ctx, 550 LayerComposition composition_type, bool enable) { 551 SCOPE_LOCK(locker_); 552 553 DisplayCompositionContext *display_comp_ctx = 554 reinterpret_cast<DisplayCompositionContext *>(display_ctx); 555 556 return display_comp_ctx->strategy->SetCompositionState(composition_type, enable); 557 } 558 559 DisplayError CompManager::ControlDpps(bool enable) { 560 if (dpps_ctrl_intf_) { 561 return enable ? dpps_ctrl_intf_->On() : dpps_ctrl_intf_->Off(); 562 } 563 564 return kErrorNone; 565 } 566 567 bool CompManager::SetDisplayState(Handle display_ctx, 568 DisplayState state, DisplayType display_type) { 569 display_state_[display_type] = state; 570 571 switch (state) { 572 case kStateOff: 573 Purge(display_ctx); 574 configured_displays_.reset(display_type); 575 DLOGV_IF(kTagCompManager, "configured_displays_ = 0x%x", configured_displays_); 576 break; 577 578 case kStateOn: 579 if (registered_displays_.count() > 1) { 580 safe_mode_ = true; 581 DLOGV_IF(kTagCompManager, "safe_mode = %d", safe_mode_); 582 } 583 break; 584 585 default: 586 break; 587 } 588 589 return true; 590 } 591 592 } // namespace sdm 593