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
Init(const HWResourceInfo & hw_res_info,ExtensionInterface * extension_intf,BufferSyncHandler * buffer_sync_handler)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
Deinit()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
RegisterDisplay(DisplayType type,const HWDisplayAttributes & display_attributes,const HWPanelInfo & hw_panel_info,const HWMixerAttributes & mixer_attributes,const DisplayConfigVariableInfo & fb_config,Handle * display_ctx)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
UnregisterDisplay(Handle comp_handle)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
ReconfigureDisplay(Handle comp_handle,const HWDisplayAttributes & display_attributes,const HWPanelInfo & hw_panel_info,const HWMixerAttributes & mixer_attributes,const DisplayConfigVariableInfo & fb_config)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
PrepareStrategyConstraints(Handle comp_handle,HWLayers * hw_layers)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
PrePrepare(Handle display_ctx,HWLayers * hw_layers)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
Prepare(Handle display_ctx,HWLayers * hw_layers)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
PostPrepare(Handle display_ctx,HWLayers * hw_layers)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
ReConfigure(Handle display_ctx,HWLayers * hw_layers)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
PostCommit(Handle display_ctx,HWLayers * hw_layers)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
Purge(Handle display_ctx)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
ProcessIdleTimeout(Handle display_ctx)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
ProcessThermalEvent(Handle display_ctx,int64_t thermal_level)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
SetMaxMixerStages(Handle display_ctx,uint32_t max_mixer_stages)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
ControlPartialUpdate(Handle display_ctx,bool enable)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
AppendDump(char * buffer,uint32_t length)408 void CompManager::AppendDump(char *buffer, uint32_t length) {
409 SCOPE_LOCK(locker_);
410 }
411
ValidateScaling(const LayerRect & crop,const LayerRect & dst,bool rotate90)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
ValidateCursorPosition(Handle display_ctx,HWLayers * hw_layers,int x,int y)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
SupportLayerAsCursor(Handle comp_handle,HWLayers * hw_layers)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
SetMaxBandwidthMode(HWBwModes mode)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
CanSetIdleTimeout(Handle display_ctx)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
GetScaleLutConfig(HWScaleLutInfo * lut_info)481 DisplayError CompManager::GetScaleLutConfig(HWScaleLutInfo *lut_info) {
482 return resource_intf_->GetScaleLutConfig(lut_info);
483 }
484
SetDetailEnhancerData(Handle display_ctx,const DisplayDetailEnhancerData & de_data)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