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