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 
86   if (!disable_gpu_comp_ && !hw_layers_info_->gpu_target_index) {
87     DLOGE("GPU composition is enabled and GPU target buffer not provided.");
88     return kErrorNotSupported;
89   }
90 
91   if (partial_update_intf_) {
92     partial_update_intf_->Start(pu_constraints);
93   }
94   GenerateROI();
95 
96   if (strategy_intf_) {
97     error = strategy_intf_->Start(hw_layers_info_, max_attempts);
98     if (error == kErrorNone) {
99       extn_start_success_ = true;
100       return kErrorNone;
101     }
102   }
103 
104   *max_attempts = 1;
105 
106   return kErrorNone;
107 }
108 
Stop()109 DisplayError Strategy::Stop() {
110   if (strategy_intf_) {
111     return strategy_intf_->Stop();
112   }
113 
114   return kErrorNone;
115 }
116 
GetNextStrategy(StrategyConstraints * constraints)117 DisplayError Strategy::GetNextStrategy(StrategyConstraints *constraints) {
118   if (extn_start_success_) {
119     return strategy_intf_->GetNextStrategy(constraints);
120   }
121 
122   // Do not fallback to GPU if GPU comp is disabled.
123   if (disable_gpu_comp_) {
124     return kErrorNotSupported;
125   }
126 
127   // Mark all application layers for GPU composition. Find GPU target buffer and store its index for
128   // programming the hardware.
129   LayerStack *layer_stack = hw_layers_info_->stack;
130   for (uint32_t i = 0; i < hw_layers_info_->app_layer_count; i++) {
131     layer_stack->layers.at(i)->composition = kCompositionGPU;
132     layer_stack->layers.at(i)->request.flags.request_flags = 0;  // Reset layer request
133   }
134 
135   // When mixer resolution and panel resolutions are same (1600x2560) and FB resolution is
136   // 1080x1920 FB_Target destination coordinates(mapped to FB resolution 1080x1920) need to
137   // be mapped to destination coordinates of mixer resolution(1600x2560).
138   Layer *gpu_target_layer = layer_stack->layers.at(hw_layers_info_->gpu_target_index);
139   float layer_mixer_width = FLOAT(mixer_attributes_.width);
140   float layer_mixer_height = FLOAT(mixer_attributes_.height);
141   float fb_width = FLOAT(fb_config_.x_pixels);
142   float fb_height = FLOAT(fb_config_.y_pixels);
143   LayerRect src_domain = (LayerRect){0.0f, 0.0f, fb_width, fb_height};
144   LayerRect dst_domain = (LayerRect){0.0f, 0.0f, layer_mixer_width, layer_mixer_height};
145 
146   Layer layer = *gpu_target_layer;
147   hw_layers_info_->index.push_back(hw_layers_info_->gpu_target_index);
148   hw_layers_info_->roi_index.push_back(0);
149   MapRect(src_domain, dst_domain, layer.dst_rect, &layer.dst_rect);
150   hw_layers_info_->hw_layers.push_back(layer);
151 
152   return kErrorNone;
153 }
154 
GenerateROI()155 void Strategy::GenerateROI() {
156   bool split_display = false;
157 
158   if (partial_update_intf_ && partial_update_intf_->GenerateROI(hw_layers_info_) == kErrorNone) {
159     return;
160   }
161 
162   float layer_mixer_width = FLOAT(mixer_attributes_.width);
163   float layer_mixer_height = FLOAT(mixer_attributes_.height);
164 
165   if (!hw_resource_info_.is_src_split && display_attributes_.is_device_split) {
166     split_display = true;
167   }
168 
169   hw_layers_info_->left_frame_roi = {};
170   hw_layers_info_->right_frame_roi = {};
171 
172   if (split_display) {
173     float left_split = FLOAT(mixer_attributes_.split_left);
174     hw_layers_info_->left_frame_roi.push_back(LayerRect(0.0f, 0.0f,
175                                 left_split, layer_mixer_height));
176     hw_layers_info_->right_frame_roi.push_back(LayerRect(left_split,
177                                 0.0f, layer_mixer_width, layer_mixer_height));
178   } else {
179     hw_layers_info_->left_frame_roi.push_back(LayerRect(0.0f, 0.0f,
180                                 layer_mixer_width, layer_mixer_height));
181     hw_layers_info_->right_frame_roi.push_back(LayerRect(0.0f, 0.0f, 0.0f, 0.0f));
182   }
183 }
184 
Reconfigure(const HWPanelInfo & hw_panel_info,const HWDisplayAttributes & display_attributes,const HWMixerAttributes & mixer_attributes,const DisplayConfigVariableInfo & fb_config)185 DisplayError Strategy::Reconfigure(const HWPanelInfo &hw_panel_info,
186                          const HWDisplayAttributes &display_attributes,
187                          const HWMixerAttributes &mixer_attributes,
188                          const DisplayConfigVariableInfo &fb_config) {
189   DisplayError error = kErrorNone;
190 
191   if (!extension_intf_) {
192     return kErrorNone;
193   }
194 
195   // TODO(user): PU Intf will not be created for video mode panels, hence re-evaluate if
196   // reconfigure is needed.
197   if (partial_update_intf_) {
198     extension_intf_->DestroyPartialUpdate(partial_update_intf_);
199     partial_update_intf_ = NULL;
200   }
201 
202   extension_intf_->CreatePartialUpdate(display_type_, hw_resource_info_, hw_panel_info,
203                                        mixer_attributes, display_attributes, fb_config,
204                                        &partial_update_intf_);
205 
206   error = strategy_intf_->Reconfigure(hw_panel_info, hw_resource_info_, mixer_attributes,
207                                       fb_config);
208   if (error != kErrorNone) {
209     return error;
210   }
211 
212   hw_panel_info_ = hw_panel_info;
213   display_attributes_ = display_attributes;
214   mixer_attributes_ = mixer_attributes;
215   fb_config_ = fb_config;
216 
217   return kErrorNone;
218 }
219 
SetCompositionState(LayerComposition composition_type,bool enable)220 DisplayError Strategy::SetCompositionState(LayerComposition composition_type, bool enable) {
221   DLOGI("composition type = %d, enable = %d", composition_type, enable);
222 
223   if (composition_type == kCompositionGPU) {
224     disable_gpu_comp_ = !enable;
225   }
226 
227   if (strategy_intf_) {
228     return strategy_intf_->SetCompositionState(composition_type, enable);
229   }
230 
231   return kErrorNone;
232 }
233 
Purge()234 DisplayError Strategy::Purge() {
235   if (strategy_intf_) {
236     return strategy_intf_->Purge();
237   }
238 
239   return kErrorNone;
240 }
241 
SetIdleTimeoutMs(uint32_t active_ms)242 DisplayError Strategy::SetIdleTimeoutMs(uint32_t active_ms) {
243   if (strategy_intf_) {
244     return strategy_intf_->SetIdleTimeoutMs(active_ms);
245   }
246 
247   return kErrorNotSupported;
248 }
249 
250 }  // namespace sdm
251