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
33namespace sdm {
34
35Strategy::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
47DisplayError 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
67DisplayError 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
79DisplayError 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
110DisplayError Strategy::Stop() {
111  if (strategy_intf_) {
112    return strategy_intf_->Stop();
113  }
114
115  return kErrorNone;
116}
117
118DisplayError 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
170void 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
200DisplayError 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
235DisplayError 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
249DisplayError Strategy::Purge() {
250  if (strategy_intf_) {
251    return strategy_intf_->Purge();
252  }
253
254  return kErrorNone;
255}
256
257
258}  // namespace sdm
259