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 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 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 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 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 115 DisplayError Strategy::Stop() { 116 if (strategy_intf_) { 117 return strategy_intf_->Stop(); 118 } 119 120 return kErrorNone; 121 } 122 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 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 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