OSDN Git Service

Fix Primary display order issues on Android.
[android-x86/external-IA-Hardware-Composer.git] / common / core / gpudevice.cpp
1 /*
2 // Copyright (c) 2016 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 #include <gpudevice.h>
18
19 #include "mosaicdisplay.h"
20
21 namespace hwcomposer {
22
23 GpuDevice::GpuDevice() : initialized_(false) {
24 }
25
26 GpuDevice::~GpuDevice() {
27   display_manager_.reset(nullptr);
28 }
29
30 bool GpuDevice::Initialize() {
31   if (initialized_)
32     return true;
33
34   initialized_ = true;
35   display_manager_.reset(DisplayManager::CreateDisplayManager());
36
37   bool success = display_manager_->Initialize();
38   if (!success) {
39     return false;
40   }
41
42   std::vector<NativeDisplay *> unordered_displays =
43       display_manager_->GetAllDisplays();
44   size_t size = unordered_displays.size();
45
46   // Handle config file reading
47   const char *hwc_dp_cfg_path = std::getenv("HWC_DISPLAY_CONFIG");
48   if (!hwc_dp_cfg_path) {
49     hwc_dp_cfg_path = "/vendor/etc/hwc_display.ini";
50   }
51
52   bool use_logical = false;
53   bool use_mosaic = false;
54   bool use_cloned = false;
55   bool rotate_display = false;
56   std::vector<uint32_t> logical_displays;
57   std::vector<uint32_t> physical_displays;
58   std::vector<uint32_t> display_rotation;
59   std::vector<std::vector<uint32_t>> cloned_displays;
60   std::vector<std::vector<uint32_t>> mosaic_displays;
61   std::ifstream fin(hwc_dp_cfg_path);
62   std::string cfg_line;
63   std::string key_logical("LOGICAL");
64   std::string key_mosaic("MOSAIC");
65   std::string key_clone("CLONE");
66   std::string key_rotate("ROTATION");
67   std::string key_logical_display("LOGICAL_DISPLAY");
68   std::string key_mosaic_display("MOSAIC_DISPLAY");
69   std::string key_physical_display("PHYSICAL_DISPLAY");
70   std::string key_physical_display_rotation("PHYSICAL_DISPLAY_ROTATION");
71   std::string key_clone_display("CLONE_DISPLAY");
72   std::vector<uint32_t> mosaic_duplicate_check;
73   std::vector<uint32_t> clone_duplicate_check;
74   std::vector<uint32_t> physical_duplicate_check;
75   std::vector<uint32_t> rotation_display_index;
76   while (std::getline(fin, cfg_line)) {
77     std::istringstream i_line(cfg_line);
78     std::string key;
79     // Skip comments
80     if (cfg_line[0] != '#' && std::getline(i_line, key, '=')) {
81       std::string content;
82       std::string value;
83       std::getline(i_line, content, '=');
84       std::istringstream i_content(content);
85       while (std::getline(i_content, value, '"')) {
86         if (value.empty())
87           continue;
88
89         std::string enable_str("true");
90         // Got logical switch
91         if (!key.compare(key_logical)) {
92           if (!value.compare(enable_str)) {
93             use_logical = true;
94           }
95           // Got mosaic switch
96         } else if (!key.compare(key_mosaic)) {
97           if (!value.compare(enable_str)) {
98             use_mosaic = true;
99           }
100           // Got clone switch
101         } else if (!key.compare(key_clone)) {
102           if (!value.compare(enable_str)) {
103             use_cloned = true;
104           }
105           // Got rotation switch.
106         } else if (!key.compare(key_rotate)) {
107           if (!value.compare(enable_str)) {
108             rotate_display = true;
109           }
110         } else if (!key.compare(key_logical_display)) {
111           std::string physical_index_str;
112           std::istringstream i_value(value);
113           // Got physical display index
114           std::getline(i_value, physical_index_str, ':');
115           if (physical_index_str.empty() ||
116               physical_index_str.find_first_not_of("0123456789") !=
117                   std::string::npos)
118             continue;
119           std::string logical_split_str;
120           // Got split num
121           std::getline(i_value, logical_split_str, ':');
122           if (logical_split_str.empty() ||
123               logical_split_str.find_first_not_of("0123456789") !=
124                   std::string::npos)
125             continue;
126           uint32_t physical_index = atoi(physical_index_str.c_str());
127           uint32_t logical_split_num = atoi(logical_split_str.c_str());
128           if (logical_split_num <= 1)
129             continue;
130           // Set logical num 1 for physical display which is not in config
131           while (physical_index > logical_displays.size()) {
132             logical_displays.emplace_back(1);
133           }
134           // Save logical split num for the physical display (don't care if the
135           // physical display is disconnected/connected here)
136           logical_displays.emplace_back(logical_split_num);
137           // Got mosaic config
138         } else if (!key.compare(key_mosaic_display)) {
139           std::istringstream i_value(value);
140           std::string i_mosaic_split_str;
141           // Got mosaic sub display num
142           std::vector<uint32_t> mosaic_display;
143           while (std::getline(i_value, i_mosaic_split_str, '+')) {
144             if (i_mosaic_split_str.empty() ||
145                 i_mosaic_split_str.find_first_not_of("0123456789") !=
146                     std::string::npos)
147               continue;
148             size_t i_mosaic_split_num = atoi(i_mosaic_split_str.c_str());
149             // Check and skip if the display already been used in other mosaic
150             bool skip_duplicate_display = false;
151             size_t mosaic_size = mosaic_duplicate_check.size();
152             for (size_t i = 0; i < mosaic_size; i++) {
153               if (mosaic_duplicate_check.at(i) == i_mosaic_split_num) {
154                 skip_duplicate_display = true;
155                 break;
156               }
157             }
158             if (!skip_duplicate_display) {
159               // save the sub display num for the mosaic display (don't care
160               // if
161               // the physical/logical display is existing/connected here)
162               mosaic_display.emplace_back(i_mosaic_split_num);
163               mosaic_duplicate_check.emplace_back(i_mosaic_split_num);
164             }
165           }
166           mosaic_displays.emplace_back(mosaic_display);
167         } else if (!key.compare(key_physical_display)) {
168           std::istringstream i_value(value);
169           std::string physical_split_str;
170           // Got physical display num
171           while (std::getline(i_value, physical_split_str, ':')) {
172             if (physical_split_str.empty() ||
173                 physical_split_str.find_first_not_of("0123456789") !=
174                     std::string::npos)
175               continue;
176             size_t physical_split_num = atoi(physical_split_str.c_str());
177             // Check and skip if the display already been used in other mosaic
178             bool skip_duplicate_display = false;
179             size_t physical_size = physical_duplicate_check.size();
180             for (size_t i = 0; i < physical_size; i++) {
181               if (physical_duplicate_check.at(i) == physical_split_num) {
182                 skip_duplicate_display = true;
183                 break;
184               }
185             }
186             if (!skip_duplicate_display) {
187               if (physical_split_num < size) {
188                 physical_displays.emplace_back(physical_split_num);
189               }
190               physical_duplicate_check.emplace_back(physical_split_num);
191             }
192           }
193         } else if (!key.compare(key_clone_display)) {
194           std::istringstream i_value(value);
195           std::string i_clone_split_str;
196           // Got mosaic sub display num
197           std::vector<uint32_t> clone_display;
198           while (std::getline(i_value, i_clone_split_str, '+')) {
199             if (i_clone_split_str.empty() ||
200                 i_clone_split_str.find_first_not_of("0123456789") !=
201                     std::string::npos)
202               continue;
203             size_t i_clone_split_num = atoi(i_clone_split_str.c_str());
204             // Check and skip if the display already been used in other clone
205             bool skip_duplicate_display = false;
206             size_t clone_size = clone_duplicate_check.size();
207             for (size_t i = 0; i < clone_size; i++) {
208               if (clone_duplicate_check.at(i) == i_clone_split_num) {
209                 skip_duplicate_display = true;
210                 break;
211               }
212             }
213             if (!skip_duplicate_display) {
214               // save the sub display num for the mosaic display (don't care
215               // if
216               // the physical/logical display is existing/connected here)
217               clone_display.emplace_back(i_clone_split_num);
218               clone_duplicate_check.emplace_back(i_clone_split_num);
219             }
220           }
221           cloned_displays.emplace_back(clone_display);
222         } else if (!key.compare(key_physical_display_rotation)) {
223           std::string physical_index_str;
224           std::istringstream i_value(value);
225           // Got physical display index
226           std::getline(i_value, physical_index_str, ':');
227           if (physical_index_str.empty() ||
228               physical_index_str.find_first_not_of("0123456789") !=
229                   std::string::npos)
230             continue;
231
232           uint32_t physical_index = atoi(physical_index_str.c_str());
233           // Check and skip if the display is already in use.
234           bool skip_duplicate_display = false;
235           size_t rotation_size = rotation_display_index.size();
236           for (size_t i = 0; i < rotation_size; i++) {
237             if (rotation_display_index.at(i) == physical_index) {
238               skip_duplicate_display = true;
239               break;
240             }
241           }
242
243           if (skip_duplicate_display) {
244             continue;
245           }
246
247           std::string rotation_str;
248           // Got split num
249           std::getline(i_value, rotation_str, ':');
250           if (rotation_str.empty() ||
251               rotation_str.find_first_not_of("0123") != std::string::npos)
252             continue;
253
254           uint32_t rotation_num = atoi(rotation_str.c_str());
255           display_rotation.emplace_back(rotation_num);
256           rotation_display_index.emplace_back(physical_index);
257         }
258       }
259     }
260   };
261
262   std::vector<NativeDisplay *> displays;
263   if (physical_displays.empty()) {
264     displays.swap(unordered_displays);
265   } else {
266     size = physical_displays.size();
267     for (size_t i = 0; i < size; i++) {
268       displays.emplace_back(unordered_displays.at(physical_displays.at(i)));
269     }
270
271     if (displays.size() != unordered_displays.size()) {
272       size = unordered_displays.size();
273       for (size_t i = 0; i < size; i++) {
274         NativeDisplay *display = unordered_displays.at(i);
275         uint32_t temp = displays.size();
276         for (size_t i = 0; i < temp; i++) {
277           if (displays.at(i) == display) {
278             display = NULL;
279             break;
280           }
281         }
282
283         if (display) {
284           displays.emplace_back(display);
285         }
286       }
287     }
288   }
289
290   // Re-order displays based on connection status.
291   std::vector<NativeDisplay *> connected_displays;
292   std::vector<NativeDisplay *> un_connected_displays;
293   size = displays.size();
294   for (size_t i = 0; i < size; i++) {
295     NativeDisplay *temp = displays.at(i);
296     if (temp->IsConnected()) {
297       connected_displays.emplace_back(temp);
298     } else {
299       un_connected_displays.emplace_back(temp);
300     }
301   }
302
303   displays.swap(connected_displays);
304
305   if (!un_connected_displays.empty()) {
306     size_t temp = un_connected_displays.size();
307     for (size_t i = 0; i < temp; i++) {
308       displays.emplace_back(un_connected_displays.at(i));
309     }
310   }
311
312   for (size_t i = 0; i < size; i++) {
313     displays.at(i)->SetDisplayOrder(i);
314   }
315
316   // We should have all displays ordered. Apply rotation settings.
317   if (rotate_display) {
318     size_t rotation_size = rotation_display_index.size();
319     for (size_t i = 0; i < rotation_size; i++) {
320       HWCRotation rotation = static_cast<HWCRotation>(display_rotation.at(i));
321       displays.at(rotation_display_index.at(i))->RotateDisplay(rotation);
322     }
323   }
324
325   // Now, we should have all physical displays ordered as required.
326   // Let's handle any Logical Display combinations or Mosaic.
327   std::vector<NativeDisplay *> temp_displays;
328   for (size_t i = 0; i < size; i++) {
329     hwcomposer::NativeDisplay *display = displays.at(i);
330     // Save logical displays to temp_displays, skip the physical display
331     if (use_logical && (logical_displays.size() >= i + 1) &&
332         logical_displays[i] > 1) {
333       std::unique_ptr<LogicalDisplayManager> manager(
334           new LogicalDisplayManager(display));
335       logical_display_manager_.emplace_back(std::move(manager));
336       // don't care if the displays is connected/disconnected here
337       logical_display_manager_.back()->InitializeLogicalDisplays(
338           logical_displays[i]);
339       std::vector<LogicalDisplay *> temp_logical_displays;
340       logical_display_manager_.back()->GetLogicalDisplays(
341           temp_logical_displays);
342       size_t logical_display_total_size = temp_logical_displays.size();
343       for (size_t j = 0; j < logical_display_total_size; j++) {
344         temp_displays.emplace_back(temp_logical_displays.at(j));
345       }
346       // Save no split physical displays to temp_displays
347     } else {
348       temp_displays.emplace_back(display);
349     }
350   }
351
352   std::vector<bool> available_displays(temp_displays.size(), true);
353   if (use_mosaic) {
354     size_t displays_size = temp_displays.size();
355     for (size_t t = 0; t < displays_size; t++) {
356       // Skip the displays which already be marked in other mosaic
357       if (!available_displays.at(t))
358         continue;
359       bool skip_display = false;
360       size_t mosaic_size = mosaic_displays.size();
361       for (size_t m = 0; m < mosaic_size; m++) {
362         std::vector<NativeDisplay *> i_available_mosaic_displays;
363         size_t mosaic_inner_size = mosaic_displays.at(m).size();
364         for (size_t l = 0; l < mosaic_inner_size; l++) {
365           // Check if the logical display is in mosaic, keep the order of
366           // logical displays list
367           // Get the smallest logical num of the mosaic for order keeping
368           if (t == mosaic_displays.at(m).at(l)) {
369             // Loop to get logical displays of mosaic, keep the order of config
370             for (size_t i = 0; i < mosaic_inner_size; i++) {
371               // Verify the logical display num
372               if (mosaic_displays.at(m).at(i) < displays_size) {
373                 // Skip the disconnected display here
374                 i_available_mosaic_displays.emplace_back(
375                     temp_displays.at(mosaic_displays.at(m).at(i)));
376                 // Add tag for mosaic-ed displays
377                 available_displays.at(mosaic_displays.at(m).at(i)) = false;
378               }
379             }
380             // Create mosaic for those logical displays
381             if (i_available_mosaic_displays.size() > 0) {
382               std::unique_ptr<MosaicDisplay> mosaic(
383                   new MosaicDisplay(i_available_mosaic_displays));
384               mosaic_displays_.emplace_back(std::move(mosaic));
385               // Save the mosaic to the final displays list
386               total_displays_.emplace_back(mosaic_displays_.back().get());
387             }
388             skip_display = true;
389             break;
390           }
391         }
392         if (skip_display)
393           break;
394       }
395       if (!skip_display) {
396         total_displays_.emplace_back(temp_displays.at(t));
397       }
398     }
399   } else {
400     total_displays_.swap(temp_displays);
401   }
402
403   if (use_cloned && !use_mosaic && !use_logical) {
404     std::vector<NativeDisplay *> temp_displays;
405     size_t displays_size = total_displays_.size();
406     size_t cloned_displays_size = cloned_displays.size();
407     for (size_t c = 0; c < cloned_displays_size; c++) {
408       std::vector<uint32_t> &temp = cloned_displays.at(c);
409       size_t c_size = temp.size();
410       NativeDisplay *physical_display = total_displays_.at(temp.at(0));
411       for (size_t clone = 1; clone < c_size; clone++) {
412         total_displays_.at(temp.at(clone))->CloneDisplay(physical_display);
413       }
414     }
415
416     for (size_t t = 0; t < displays_size; t++) {
417       bool found = false;
418       for (size_t c = 0; c < cloned_displays_size; c++) {
419         std::vector<uint32_t> &temp = cloned_displays.at(c);
420         size_t c_size = temp.size();
421         for (size_t clone = 1; clone < c_size; clone++) {
422           uint32_t temp_clone = temp.at(clone);
423           if (temp_clone == t) {
424             found = true;
425             break;
426           }
427         }
428
429         if (found) {
430           break;
431         }
432       }
433
434       // Don't advertise cloned display as another independent
435       // Physical Display.
436       if (found) {
437         continue;
438       }
439
440       temp_displays.emplace_back(total_displays_.at(t));
441     }
442
443     temp_displays.swap(total_displays_);
444   }
445
446   return true;
447 }
448
449 NativeDisplay *GpuDevice::GetDisplay(uint32_t display_id) {
450   if (total_displays_.size() > display_id)
451     return total_displays_.at(display_id);
452
453   return NULL;
454 }
455
456 NativeDisplay *GpuDevice::GetVirtualDisplay() {
457   return display_manager_->GetVirtualDisplay();
458 }
459
460 void GpuDevice::GetConnectedPhysicalDisplays(
461     std::vector<NativeDisplay *> &displays) {
462   size_t size = total_displays_.size();
463   for (size_t i = 0; i < size; i++) {
464     if (total_displays_.at(i)->IsConnected()) {
465       displays.emplace_back(total_displays_.at(i));
466     }
467   }
468 }
469
470 std::vector<NativeDisplay *> GpuDevice::GetAllDisplays() {
471   return total_displays_;
472 }
473
474 void GpuDevice::RegisterHotPlugEventCallback(
475     std::shared_ptr<DisplayHotPlugEventCallback> callback) {
476   display_manager_->RegisterHotPlugEventCallback(callback);
477 }
478
479 }  // namespace hwcomposer