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