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