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