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