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 
28 #include "strategy.h"
29 
30 #define __CLASS__ "Strategy"
31 
32 namespace sdm {
33 
Strategy(ExtensionInterface * extension_intf,DisplayType type,const HWResourceInfo & hw_resource_info,const HWPanelInfo & hw_panel_info,const HWMixerAttributes & mixer_attributes,const HWDisplayAttributes & display_attributes,const DisplayConfigVariableInfo & fb_config)34 Strategy::Strategy(ExtensionInterface *extension_intf, DisplayType type,
35                    const HWResourceInfo &hw_resource_info, const HWPanelInfo &hw_panel_info,
36                    const HWMixerAttributes &mixer_attributes,
37                    const HWDisplayAttributes &display_attributes,
38                    const DisplayConfigVariableInfo &fb_config)
39   : extension_intf_(extension_intf), display_type_(type), hw_resource_info_(hw_resource_info),
40     hw_panel_info_(hw_panel_info), mixer_attributes_(mixer_attributes),
41     display_attributes_(display_attributes), fb_config_(fb_config) {
42 }
43 
Init()44 DisplayError Strategy::Init() {
45   DisplayError error = kErrorNone;
46 
47   if (extension_intf_) {
48     error = extension_intf_->CreateStrategyExtn(display_type_, hw_panel_info_.mode,
49                                                 hw_panel_info_.s3d_mode, mixer_attributes_,
50                                                 fb_config_, &strategy_intf_);
51     if (error != kErrorNone) {
52       DLOGE("Failed to create strategy");
53       return error;
54     }
55 
56     error = extension_intf_->CreatePartialUpdate(display_type_, hw_resource_info_, hw_panel_info_,
57                                                  mixer_attributes_, display_attributes_,
58                                                  &partial_update_intf_);
59   }
60 
61   return kErrorNone;
62 }
63 
Deinit()64 DisplayError Strategy::Deinit() {
65   if (strategy_intf_) {
66     if (partial_update_intf_) {
67       extension_intf_->DestroyPartialUpdate(partial_update_intf_);
68     }
69 
70     extension_intf_->DestroyStrategyExtn(strategy_intf_);
71   }
72 
73   return kErrorNone;
74 }
75 
Start(HWLayersInfo * hw_layers_info,uint32_t * max_attempts,bool partial_update_enable)76 DisplayError Strategy::Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempts,
77                              bool partial_update_enable) {
78   DisplayError error = kErrorNone;
79 
80   hw_layers_info_ = hw_layers_info;
81   extn_start_success_ = false;
82   tried_default_ = false;
83   uint32_t i = 0;
84   LayerStack *layer_stack = hw_layers_info_->stack;
85   uint32_t layer_count = UINT32(layer_stack->layers.size());
86   for (; i < layer_count; i++) {
87     if (layer_stack->layers.at(i)->composition == kCompositionGPUTarget) {
88       fb_layer_index_ = i;
89       break;
90     }
91   }
92 
93   if (i == layer_count) {
94     return kErrorUndefined;
95   }
96 
97   if (partial_update_intf_) {
98     partial_update_intf_->ControlPartialUpdate(partial_update_enable);
99   }
100   GenerateROI();
101 
102   if (strategy_intf_) {
103     error = strategy_intf_->Start(hw_layers_info_, max_attempts);
104     if (error == kErrorNone) {
105       extn_start_success_ = true;
106       return kErrorNone;
107     }
108   }
109 
110   *max_attempts = 1;
111 
112   return kErrorNone;
113 }
114 
Stop()115 DisplayError Strategy::Stop() {
116   if (strategy_intf_) {
117     return strategy_intf_->Stop();
118   }
119 
120   return kErrorNone;
121 }
122 
GetNextStrategy(StrategyConstraints * constraints)123 DisplayError Strategy::GetNextStrategy(StrategyConstraints *constraints) {
124   DisplayError error = kErrorNone;
125 
126   if (extn_start_success_) {
127     error = strategy_intf_->GetNextStrategy(constraints);
128     if (error == kErrorNone) {
129       return kErrorNone;
130     }
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   uint32_t &hw_layer_count = hw_layers_info_->count;
142   hw_layer_count = 0;
143 
144   for (uint32_t i = 0; i < layer_stack->layers.size(); i++) {
145     Layer *layer = layer_stack->layers.at(i);
146     LayerComposition &composition = layer->composition;
147     if (composition == kCompositionGPUTarget) {
148       hw_layers_info_->updated_src_rect[hw_layer_count] = layer->src_rect;
149       hw_layers_info_->updated_dst_rect[hw_layer_count] = layer->dst_rect;
150       hw_layers_info_->index[hw_layer_count++] = i;
151     } else if (composition != kCompositionBlitTarget) {
152       composition = kCompositionGPU;
153     }
154   }
155 
156   tried_default_ = true;
157 
158   // There can be one and only one GPU target buffer.
159   if (hw_layer_count != 1) {
160     return kErrorParameters;
161   }
162 
163   return kErrorNone;
164 }
165 
GenerateROI()166 void Strategy::GenerateROI() {
167   bool split_display = false;
168 
169   if (partial_update_intf_ && partial_update_intf_->GenerateROI(hw_layers_info_) == kErrorNone) {
170     return;
171   }
172 
173   float layer_mixer_width = mixer_attributes_.width;
174   float layer_mixer_height = mixer_attributes_.height;
175 
176   if (!hw_resource_info_.is_src_split &&
177      ((layer_mixer_width > hw_resource_info_.max_mixer_width) ||
178      ((hw_panel_info_.is_primary_panel) && hw_panel_info_.split_info.right_split))) {
179     split_display = true;
180   }
181 
182   if (split_display) {
183     float left_split = FLOAT(mixer_attributes_.split_left);
184     hw_layers_info_->left_partial_update = (LayerRect) {0.0f, 0.0f, left_split, layer_mixer_height};
185     hw_layers_info_->right_partial_update = (LayerRect) {left_split, 0.0f, layer_mixer_width,
186                                             layer_mixer_height};
187   } else {
188     hw_layers_info_->left_partial_update = (LayerRect) {0.0f, 0.0f, layer_mixer_width,
189                                            layer_mixer_height};
190     hw_layers_info_->right_partial_update = (LayerRect) {0.0f, 0.0f, 0.0f, 0.0f};
191   }
192 }
193 
Reconfigure(const HWPanelInfo & hw_panel_info,const HWDisplayAttributes & display_attributes,const HWMixerAttributes & mixer_attributes,const DisplayConfigVariableInfo & fb_config)194 DisplayError Strategy::Reconfigure(const HWPanelInfo &hw_panel_info,
195                          const HWDisplayAttributes &display_attributes,
196                          const HWMixerAttributes &mixer_attributes,
197                          const DisplayConfigVariableInfo &fb_config) {
198   hw_panel_info_ = hw_panel_info;
199   display_attributes_ = display_attributes;
200   mixer_attributes_ = mixer_attributes;
201 
202   if (!extension_intf_) {
203     return kErrorNone;
204   }
205 
206   // TODO(user): PU Intf will not be created for video mode panels, hence re-evaluate if
207   // reconfigure is needed.
208   if (partial_update_intf_) {
209     extension_intf_->DestroyPartialUpdate(partial_update_intf_);
210     partial_update_intf_ = NULL;
211   }
212 
213   extension_intf_->CreatePartialUpdate(display_type_, hw_resource_info_, hw_panel_info_,
214                                        mixer_attributes_, display_attributes_,
215                                        &partial_update_intf_);
216 
217   return strategy_intf_->Reconfigure(hw_panel_info_.mode, hw_panel_info_.s3d_mode, mixer_attributes,
218                                      fb_config);
219 }
220 
221 }  // namespace sdm
222