1 /*
2 * Copyright (c) 2014 - 2017, 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 
28 #include "strategy.h"
29 #include "utils/rect.h"
30 
31 #define __CLASS__ "Strategy"
32 
33 namespace sdm {
34 
Strategy(ExtensionInterface * extension_intf,BufferAllocator * buffer_allocator,DisplayType type,const HWResourceInfo & hw_resource_info,const HWPanelInfo & hw_panel_info,const HWMixerAttributes & mixer_attributes,const HWDisplayAttributes & display_attributes,const DisplayConfigVariableInfo & fb_config)35 Strategy::Strategy(ExtensionInterface *extension_intf, BufferAllocator *buffer_allocator,
36                    DisplayType type,
37                    const HWResourceInfo &hw_resource_info, const HWPanelInfo &hw_panel_info,
38                    const HWMixerAttributes &mixer_attributes,
39                    const HWDisplayAttributes &display_attributes,
40                    const DisplayConfigVariableInfo &fb_config)
41   : extension_intf_(extension_intf), display_type_(type), hw_resource_info_(hw_resource_info),
42     hw_panel_info_(hw_panel_info), mixer_attributes_(mixer_attributes),
43     display_attributes_(display_attributes), fb_config_(fb_config),
44     buffer_allocator_(buffer_allocator) {
45 }
46 
Init()47 DisplayError Strategy::Init() {
48   DisplayError error = kErrorNone;
49 
50   if (extension_intf_) {
51     error = extension_intf_->CreateStrategyExtn(display_type_, buffer_allocator_, hw_resource_info_,
52                                                 hw_panel_info_, mixer_attributes_, fb_config_,
53                                                 &strategy_intf_);
54     if (error != kErrorNone) {
55       DLOGE("Failed to create strategy");
56       return error;
57     }
58 
59     error = extension_intf_->CreatePartialUpdate(display_type_, hw_resource_info_, hw_panel_info_,
60                                                  mixer_attributes_, display_attributes_, fb_config_,
61                                                  &partial_update_intf_);
62   }
63 
64   return kErrorNone;
65 }
66 
Deinit()67 DisplayError Strategy::Deinit() {
68   if (strategy_intf_) {
69     if (partial_update_intf_) {
70       extension_intf_->DestroyPartialUpdate(partial_update_intf_);
71     }
72 
73     extension_intf_->DestroyStrategyExtn(strategy_intf_);
74   }
75 
76   return kErrorNone;
77 }
78 
Start(HWLayersInfo * hw_layers_info,uint32_t * max_attempts,const PUConstraints & pu_constraints)79 DisplayError Strategy::Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempts,
80                              const PUConstraints &pu_constraints) {
81   DisplayError error = kErrorNone;
82 
83   hw_layers_info_ = hw_layers_info;
84   extn_start_success_ = false;
85   tried_default_ = false;
86 
87   if (!disable_gpu_comp_ && !hw_layers_info_->gpu_target_index) {
88     DLOGE("GPU composition is enabled and GPU target buffer not provided.");
89     return kErrorNotSupported;
90   }
91 
92   if (partial_update_intf_) {
93     partial_update_intf_->Start(pu_constraints);
94   }
95   GenerateROI();
96 
97   if (strategy_intf_) {
98     error = strategy_intf_->Start(hw_layers_info_, max_attempts);
99     if (error == kErrorNone) {
100       extn_start_success_ = true;
101       return kErrorNone;
102     }
103   }
104 
105   *max_attempts = 1;
106 
107   return kErrorNone;
108 }
109 
Stop()110 DisplayError Strategy::Stop() {
111   if (strategy_intf_) {
112     return strategy_intf_->Stop();
113   }
114 
115   return kErrorNone;
116 }
117 
GetNextStrategy(StrategyConstraints * constraints)118 DisplayError Strategy::GetNextStrategy(StrategyConstraints *constraints) {
119   DisplayError error = kErrorNone;
120 
121   if (extn_start_success_) {
122     error = strategy_intf_->GetNextStrategy(constraints);
123     if (error == kErrorNone) {
124       return kErrorNone;
125     }
126   }
127 
128   // Do not fallback to GPU if GPU comp is disabled.
129   if (disable_gpu_comp_) {
130     return kErrorNotSupported;
131   }
132 
133   // Default composition is already tried.
134   if (tried_default_) {
135     return kErrorUndefined;
136   }
137 
138   // Mark all application layers for GPU composition. Find GPU target buffer and store its index for
139   // programming the hardware.
140   LayerStack *layer_stack = hw_layers_info_->stack;
141   for (uint32_t i = 0; i < hw_layers_info_->app_layer_count; i++) {
142     layer_stack->layers.at(i)->composition = kCompositionGPU;
143     layer_stack->layers.at(i)->request.flags.request_flags = 0;  // Reset layer request
144   }
145 
146   if (!extn_start_success_) {
147     // When mixer resolution and panel resolutions are same (1600x2560) and FB resolution is
148     // 1080x1920 FB_Target destination coordinates(mapped to FB resolution 1080x1920) need to
149     // be mapped to destination coordinates of mixer resolution(1600x2560).
150     Layer *gpu_target_layer = layer_stack->layers.at(hw_layers_info_->gpu_target_index);
151     float layer_mixer_width = FLOAT(mixer_attributes_.width);
152     float layer_mixer_height = FLOAT(mixer_attributes_.height);
153     float fb_width = FLOAT(fb_config_.x_pixels);
154     float fb_height = FLOAT(fb_config_.y_pixels);
155     LayerRect src_domain = (LayerRect){0.0f, 0.0f, fb_width, fb_height};
156     LayerRect dst_domain = (LayerRect){0.0f, 0.0f, layer_mixer_width, layer_mixer_height};
157 
158     Layer layer = *gpu_target_layer;
159     hw_layers_info_->index[0] = hw_layers_info_->gpu_target_index;
160     MapRect(src_domain, dst_domain, layer.dst_rect, &layer.dst_rect);
161     hw_layers_info_->hw_layers.clear();
162     hw_layers_info_->hw_layers.push_back(layer);
163   }
164 
165   tried_default_ = true;
166 
167   return kErrorNone;
168 }
169 
GenerateROI()170 void Strategy::GenerateROI() {
171   bool split_display = false;
172 
173   if (partial_update_intf_ && partial_update_intf_->GenerateROI(hw_layers_info_) == kErrorNone) {
174     return;
175   }
176 
177   float layer_mixer_width = mixer_attributes_.width;
178   float layer_mixer_height = mixer_attributes_.height;
179 
180   if (!hw_resource_info_.is_src_split && display_attributes_.is_device_split) {
181     split_display = true;
182   }
183 
184   hw_layers_info_->left_frame_roi = {};
185   hw_layers_info_->right_frame_roi = {};
186 
187   if (split_display) {
188     float left_split = FLOAT(mixer_attributes_.split_left);
189     hw_layers_info_->left_frame_roi.push_back(LayerRect(0.0f, 0.0f,
190                                 left_split, layer_mixer_height));
191     hw_layers_info_->right_frame_roi.push_back(LayerRect(left_split,
192                                 0.0f, layer_mixer_width, layer_mixer_height));
193   } else {
194     hw_layers_info_->left_frame_roi.push_back(LayerRect(0.0f, 0.0f,
195                                 layer_mixer_width, layer_mixer_height));
196     hw_layers_info_->right_frame_roi.push_back(LayerRect(0.0f, 0.0f, 0.0f, 0.0f));
197   }
198 }
199 
Reconfigure(const HWPanelInfo & hw_panel_info,const HWDisplayAttributes & display_attributes,const HWMixerAttributes & mixer_attributes,const DisplayConfigVariableInfo & fb_config)200 DisplayError Strategy::Reconfigure(const HWPanelInfo &hw_panel_info,
201                          const HWDisplayAttributes &display_attributes,
202                          const HWMixerAttributes &mixer_attributes,
203                          const DisplayConfigVariableInfo &fb_config) {
204   DisplayError error = kErrorNone;
205 
206   if (!extension_intf_) {
207     return kErrorNone;
208   }
209 
210   // TODO(user): PU Intf will not be created for video mode panels, hence re-evaluate if
211   // reconfigure is needed.
212   if (partial_update_intf_) {
213     extension_intf_->DestroyPartialUpdate(partial_update_intf_);
214     partial_update_intf_ = NULL;
215   }
216 
217   extension_intf_->CreatePartialUpdate(display_type_, hw_resource_info_, hw_panel_info,
218                                        mixer_attributes, display_attributes, fb_config,
219                                        &partial_update_intf_);
220 
221   error = strategy_intf_->Reconfigure(hw_panel_info, hw_resource_info_, mixer_attributes,
222                                       fb_config);
223   if (error != kErrorNone) {
224     return error;
225   }
226 
227   hw_panel_info_ = hw_panel_info;
228   display_attributes_ = display_attributes;
229   mixer_attributes_ = mixer_attributes;
230   fb_config_ = fb_config;
231 
232   return kErrorNone;
233 }
234 
SetCompositionState(LayerComposition composition_type,bool enable)235 DisplayError Strategy::SetCompositionState(LayerComposition composition_type, bool enable) {
236   DLOGI("composition type = %d, enable = %d", composition_type, enable);
237 
238   if (composition_type == kCompositionGPU) {
239     disable_gpu_comp_ = !enable;
240   }
241 
242   if (strategy_intf_) {
243     return strategy_intf_->SetCompositionState(composition_type, enable);
244   }
245 
246   return kErrorNone;
247 }
248 
Purge()249 DisplayError Strategy::Purge() {
250   if (strategy_intf_) {
251     return strategy_intf_->Purge();
252   }
253 
254   return kErrorNone;
255 }
256 
SetIdleTimeoutMs(uint32_t active_ms)257 DisplayError Strategy::SetIdleTimeoutMs(uint32_t active_ms) {
258   if (strategy_intf_) {
259     return strategy_intf_->SetIdleTimeoutMs(active_ms);
260   }
261 
262   return kErrorNotSupported;
263 }
264 
265 }  // namespace sdm
266