2 // Copyright (c) 2016 Intel Corporation
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <gpudevice.h>
19 #include "mosaicdisplay.h"
21 namespace hwcomposer {
23 GpuDevice::GpuDevice() : initialized_(false) {
26 GpuDevice::~GpuDevice() {
27 display_manager_.reset(nullptr);
30 bool GpuDevice::Initialize() {
35 display_manager_.reset(DisplayManager::CreateDisplayManager());
37 bool success = display_manager_->Initialize();
42 std::vector<NativeDisplay *> unordered_displays =
43 display_manager_->GetAllDisplays();
44 size_t size = unordered_displays.size();
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";
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);
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);
80 if (cfg_line[0] != '#' && std::getline(i_line, key, '=')) {
83 std::getline(i_line, content, '=');
84 std::istringstream i_content(content);
85 while (std::getline(i_content, value, '"')) {
89 std::string enable_str("true");
91 if (!key.compare(key_logical)) {
92 if (!value.compare(enable_str)) {
96 } else if (!key.compare(key_mosaic)) {
97 if (!value.compare(enable_str)) {
101 } else if (!key.compare(key_clone)) {
102 if (!value.compare(enable_str)) {
105 // Got rotation switch.
106 } else if (!key.compare(key_rotate)) {
107 if (!value.compare(enable_str)) {
108 rotate_display = true;
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") !=
119 std::string logical_split_str;
121 std::getline(i_value, logical_split_str, ':');
122 if (logical_split_str.empty() ||
123 logical_split_str.find_first_not_of("0123456789") !=
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)
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);
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);
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") !=
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;
158 if (!skip_duplicate_display) {
159 // save the sub display num for the mosaic display (don't care
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);
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") !=
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;
186 if (!skip_duplicate_display) {
187 if (physical_split_num < size) {
188 physical_displays.emplace_back(physical_split_num);
190 physical_duplicate_check.emplace_back(physical_split_num);
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") !=
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;
213 if (!skip_duplicate_display) {
214 // save the sub display num for the mosaic display (don't care
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);
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") !=
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;
243 if (skip_duplicate_display) {
247 std::string rotation_str;
249 std::getline(i_value, rotation_str, ':');
250 if (rotation_str.empty() ||
251 rotation_str.find_first_not_of("0123") != std::string::npos)
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);
262 std::vector<NativeDisplay *> displays;
263 if (physical_displays.empty()) {
264 displays.swap(unordered_displays);
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)));
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) {
284 displays.emplace_back(display);
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);
299 un_connected_displays.emplace_back(temp);
303 displays.swap(connected_displays);
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));
312 for (size_t i = 0; i < size; i++) {
313 displays.at(i)->SetDisplayOrder(i);
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);
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));
346 // Save no split physical displays to temp_displays
348 temp_displays.emplace_back(display);
352 std::vector<bool> available_displays(temp_displays.size(), true);
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))
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;
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());
396 total_displays_.emplace_back(temp_displays.at(t));
400 total_displays_.swap(temp_displays);
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);
416 for (size_t t = 0; t < displays_size; t++) {
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) {
434 // Don't advertise cloned display as another independent
440 temp_displays.emplace_back(total_displays_.at(t));
443 temp_displays.swap(total_displays_);
449 NativeDisplay *GpuDevice::GetDisplay(uint32_t display_id) {
450 if (total_displays_.size() > display_id)
451 return total_displays_.at(display_id);
456 NativeDisplay *GpuDevice::GetVirtualDisplay() {
457 return display_manager_->GetVirtualDisplay();
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));
470 std::vector<NativeDisplay *> GpuDevice::GetAllDisplays() {
471 return total_displays_;
474 void GpuDevice::RegisterHotPlugEventCallback(
475 std::shared_ptr<DisplayHotPlugEventCallback> callback) {
476 display_manager_->RegisterHotPlugEventCallback(callback);
479 } // namespace hwcomposer