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