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