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