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
32namespace sdm {
33
34Strategy::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
44DisplayError 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
64DisplayError 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
76DisplayError 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
115DisplayError Strategy::Stop() {
116  if (strategy_intf_) {
117    return strategy_intf_->Stop();
118  }
119
120  return kErrorNone;
121}
122
123DisplayError 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
166void 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
194DisplayError 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