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 
Strategy(ExtensionInterface * extension_intf,DisplayType type,const HWResourceInfo & hw_resource_info,const HWPanelInfo & hw_panel_info,const HWDisplayAttributes & hw_display_attributes)34 Strategy::Strategy(ExtensionInterface *extension_intf, DisplayType type,
35                    const HWResourceInfo &hw_resource_info, const HWPanelInfo &hw_panel_info,
36                    const HWDisplayAttributes &hw_display_attributes)
37   : extension_intf_(extension_intf), display_type_(type), hw_resource_info_(hw_resource_info),
38     hw_panel_info_(hw_panel_info), hw_display_attributes_(hw_display_attributes) {
39 }
40 
Init()41 DisplayError Strategy::Init() {
42   DisplayError error = kErrorNone;
43 
44   if (extension_intf_) {
45     error = extension_intf_->CreateStrategyExtn(display_type_, hw_panel_info_.mode,
46                                                 hw_panel_info_.s3d_mode, &strategy_intf_);
47     if (error != kErrorNone) {
48       DLOGE("Failed to create strategy");
49       return error;
50     }
51 
52     error = extension_intf_->CreatePartialUpdate(display_type_, hw_resource_info_,
53                                                  hw_panel_info_, &partial_update_intf_);
54   }
55 
56   return kErrorNone;
57 }
58 
Deinit()59 DisplayError Strategy::Deinit() {
60   if (strategy_intf_) {
61     if (partial_update_intf_) {
62       extension_intf_->DestroyPartialUpdate(partial_update_intf_);
63     }
64 
65     extension_intf_->DestroyStrategyExtn(strategy_intf_);
66   }
67 
68   return kErrorNone;
69 }
70 
Start(HWLayersInfo * hw_layers_info,uint32_t * max_attempts,bool partial_update_enable)71 DisplayError Strategy::Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempts,
72                              bool partial_update_enable) {
73   DisplayError error = kErrorNone;
74 
75   hw_layers_info_ = hw_layers_info;
76   extn_start_success_ = false;
77   tried_default_ = false;
78 
79   uint32_t i = 0;
80   LayerStack *layer_stack = hw_layers_info_->stack;
81   for (; i < layer_stack->layer_count; i++) {
82     if (layer_stack->layers[i].composition == kCompositionGPUTarget) {
83       fb_layer_index_ = i;
84       break;
85     }
86   }
87 
88   if (i == layer_stack->layer_count) {
89     return kErrorUndefined;
90   }
91 
92   if (partial_update_intf_) {
93     partial_update_intf_->ControlPartialUpdate(partial_update_enable);
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 (extn_start_success_) {
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   // Default composition is already tried.
129   if (tried_default_) {
130     return kErrorUndefined;
131   }
132 
133   // Mark all application layers for GPU composition. Find GPU target buffer and store its index for
134   // programming the hardware.
135   LayerStack *layer_stack = hw_layers_info_->stack;
136   uint32_t &hw_layer_count = hw_layers_info_->count;
137   hw_layer_count = 0;
138 
139   for (uint32_t i = 0; i < layer_stack->layer_count; i++) {
140     LayerComposition &composition = layer_stack->layers[i].composition;
141     if (composition == kCompositionGPUTarget) {
142       hw_layers_info_->updated_src_rect[hw_layer_count] = layer_stack->layers[i].src_rect;
143       hw_layers_info_->updated_dst_rect[hw_layer_count] = layer_stack->layers[i].dst_rect;
144       hw_layers_info_->index[hw_layer_count++] = i;
145     } else if (composition != kCompositionBlitTarget) {
146       composition = kCompositionGPU;
147     }
148   }
149 
150   tried_default_ = true;
151 
152   // There can be one and only one GPU target buffer.
153   if (hw_layer_count != 1) {
154     return kErrorParameters;
155   }
156 
157   return kErrorNone;
158 }
159 
GenerateROI()160 void Strategy::GenerateROI() {
161   bool split_display = false;
162 
163   if (partial_update_intf_ && partial_update_intf_->GenerateROI(hw_layers_info_) == kErrorNone) {
164     return;
165   }
166 
167   float disp_x_res = hw_display_attributes_.x_pixels;
168   float disp_y_res = hw_display_attributes_.y_pixels;
169 
170   if (!hw_resource_info_.is_src_split &&
171      ((disp_x_res > hw_resource_info_.max_mixer_width) ||
172      ((display_type_ == kPrimary) && hw_panel_info_.split_info.right_split))) {
173     split_display = true;
174   }
175 
176   if (split_display) {
177     float left_split = FLOAT(hw_panel_info_.split_info.left_split);
178     hw_layers_info_->left_partial_update = (LayerRect) {0.0f, 0.0f, left_split, disp_y_res};
179     hw_layers_info_->right_partial_update = (LayerRect) {left_split, 0.0f, disp_x_res, disp_y_res};
180   } else {
181     hw_layers_info_->left_partial_update = (LayerRect) {0.0f, 0.0f, disp_x_res, disp_y_res};
182     hw_layers_info_->right_partial_update = (LayerRect) {0.0f, 0.0f, 0.0f, 0.0f};
183   }
184 }
185 
186 }  // namespace sdm
187 
188