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