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>
21 #include "mosaicdisplay.h"
25 namespace hwcomposer {
27 GpuDevice::GpuDevice() : HWCThread(-8, "GpuDevice") {
30 GpuDevice::~GpuDevice() {
31 display_manager_.reset(nullptr);
34 bool GpuDevice::Initialize() {
35 initialization_state_lock_.lock();
36 if (initialization_state_ & kInitialized) {
37 initialization_state_lock_.unlock();
41 initialization_state_ |= kInitialized;
42 initialization_state_lock_.unlock();
44 display_manager_.reset(DisplayManager::CreateDisplayManager(this));
46 bool success = display_manager_->Initialize();
51 display_manager_->InitializeDisplayResources();
52 display_manager_->StartHotPlugMonitor();
56 lock_fd_ = open("/vendor/hwc.lock", O_RDONLY);
59 ETRACE("Failed to initalize thread for GpuDevice. %s", PRINTERROR());
62 ITRACE("Failed to open " LOCK_DIR_PREFIX "/hwc.lock file!");
68 uint32_t GpuDevice::GetFD() const {
69 return display_manager_->GetFD();
72 NativeDisplay *GpuDevice::GetDisplay(uint32_t display_id) {
73 if (total_displays_.size() > display_id)
74 return total_displays_.at(display_id);
79 NativeDisplay *GpuDevice::CreateVirtualDisplay(uint32_t display_index) {
80 return display_manager_->CreateVirtualDisplay(display_index);
83 void GpuDevice::DestroyVirtualDisplay(uint32_t display_index) {
84 display_manager_->DestroyVirtualDisplay(display_index);
87 void GpuDevice::GetConnectedPhysicalDisplays(
88 std::vector<NativeDisplay *> &displays) {
89 size_t size = total_displays_.size();
90 for (size_t i = 0; i < size; i++) {
91 if (total_displays_.at(i)->IsConnected()) {
92 displays.emplace_back(total_displays_.at(i));
97 const std::vector<NativeDisplay *> &GpuDevice::GetAllDisplays() {
98 return total_displays_;
101 void GpuDevice::RegisterHotPlugEventCallback(
102 std::shared_ptr<DisplayHotPlugEventCallback> callback) {
103 display_manager_->RegisterHotPlugEventCallback(callback);
106 void GpuDevice::HandleHWCSettings() {
107 // Handle config file reading
108 const char *hwc_dp_cfg_path = HWC_DISPLAY_INI_PATH;
109 ITRACE("Hwc display config file is %s", hwc_dp_cfg_path);
111 bool use_logical = false;
112 bool use_mosaic = false;
113 bool use_cloned = false;
114 bool rotate_display = false;
115 bool use_float = false;
116 std::vector<uint32_t> logical_displays;
117 std::vector<uint32_t> physical_displays;
118 std::vector<uint32_t> display_rotation;
119 std::vector<uint32_t> float_display_indices;
120 std::vector<HwcRect<int32_t>> float_displays;
121 std::vector<std::vector<uint32_t>> cloned_displays;
122 std::vector<std::vector<uint32_t>> mosaic_displays;
123 std::ifstream fin(hwc_dp_cfg_path);
124 std::string cfg_line;
125 std::string key_logical("LOGICAL");
126 std::string key_mosaic("MOSAIC");
127 std::string key_clone("CLONE");
128 std::string key_rotate("ROTATION");
129 std::string key_float("FLOAT");
130 std::string key_logical_display("LOGICAL_DISPLAY");
131 std::string key_mosaic_display("MOSAIC_DISPLAY");
132 std::string key_physical_display("PHYSICAL_DISPLAY");
133 std::string key_physical_display_rotation("PHYSICAL_DISPLAY_ROTATION");
134 std::string key_clone_display("CLONE_DISPLAY");
135 std::string key_float_display("FLOAT_DISPLAY");
136 std::vector<uint32_t> mosaic_duplicate_check;
137 std::vector<uint32_t> clone_duplicate_check;
138 std::vector<uint32_t> physical_duplicate_check;
139 std::vector<uint32_t> rotation_display_index;
140 while (std::getline(fin, cfg_line)) {
141 std::istringstream i_line(cfg_line);
144 if (cfg_line[0] != '#' && std::getline(i_line, key, '=')) {
147 std::getline(i_line, content, '=');
148 std::istringstream i_content(content);
149 while (std::getline(i_content, value, '"')) {
153 std::string enable_str("true");
154 // Got logical switch
155 if (!key.compare(key_logical)) {
156 if (!value.compare(enable_str)) {
160 } else if (!key.compare(key_mosaic)) {
161 if (!value.compare(enable_str)) {
165 } else if (!key.compare(key_clone)) {
166 if (!value.compare(enable_str)) {
169 // Got rotation switch.
170 } else if (!key.compare(key_rotate)) {
171 if (!value.compare(enable_str)) {
172 rotate_display = true;
175 } else if (!key.compare(key_float)) {
176 if (!value.compare(enable_str)) {
179 } else if (!key.compare(key_logical_display)) {
180 std::string physical_index_str;
181 std::istringstream i_value(value);
182 // Got physical display index
183 std::getline(i_value, physical_index_str, ':');
184 if (physical_index_str.empty() ||
185 physical_index_str.find_first_not_of("0123456789") !=
188 std::string logical_split_str;
190 std::getline(i_value, logical_split_str, ':');
191 if (logical_split_str.empty() ||
192 logical_split_str.find_first_not_of("0123456789") !=
195 uint32_t physical_index = atoi(physical_index_str.c_str());
196 uint32_t logical_split_num = atoi(logical_split_str.c_str());
197 if (logical_split_num <= 1)
199 // Set logical num 1 for physical display which is not in config
200 while (physical_index > logical_displays.size()) {
201 logical_displays.emplace_back(1);
203 // Save logical split num for the physical display (don't care if the
204 // physical display is disconnected/connected here)
205 logical_displays.emplace_back(logical_split_num);
207 } else if (!key.compare(key_mosaic_display)) {
208 std::istringstream i_value(value);
209 std::string i_mosaic_split_str;
210 // Got mosaic sub display num
211 std::vector<uint32_t> mosaic_display;
212 while (std::getline(i_value, i_mosaic_split_str, '+')) {
213 if (i_mosaic_split_str.empty() ||
214 i_mosaic_split_str.find_first_not_of("0123456789") !=
217 size_t i_mosaic_split_num = atoi(i_mosaic_split_str.c_str());
218 // Check and skip if the display already been used in other mosaic
219 bool skip_duplicate_display = false;
220 size_t mosaic_size = mosaic_duplicate_check.size();
221 for (size_t i = 0; i < mosaic_size; i++) {
222 if (mosaic_duplicate_check.at(i) == i_mosaic_split_num) {
223 skip_duplicate_display = true;
227 if (!skip_duplicate_display) {
228 // save the sub display num for the mosaic display (don't care
230 // the physical/logical display is existing/connected here)
231 mosaic_display.emplace_back(i_mosaic_split_num);
232 mosaic_duplicate_check.emplace_back(i_mosaic_split_num);
235 mosaic_displays.emplace_back(mosaic_display);
236 } else if (!key.compare(key_physical_display)) {
237 std::istringstream i_value(value);
238 std::string physical_split_str;
239 // Got physical display num
240 while (std::getline(i_value, physical_split_str, ':')) {
241 if (physical_split_str.empty() ||
242 physical_split_str.find_first_not_of("0123456789") !=
245 size_t physical_split_num = atoi(physical_split_str.c_str());
246 // Check and skip if the display already been used in other mosaic
247 bool skip_duplicate_display = false;
248 size_t physical_size = physical_duplicate_check.size();
249 for (size_t i = 0; i < physical_size; i++) {
250 if (physical_duplicate_check.at(i) == physical_split_num) {
251 skip_duplicate_display = true;
255 if (!skip_duplicate_display) {
256 physical_displays.emplace_back(physical_split_num);
257 physical_duplicate_check.emplace_back(physical_split_num);
260 } else if (!key.compare(key_clone_display)) {
261 std::istringstream i_value(value);
262 std::string i_clone_split_str;
263 // Got mosaic sub display num
264 std::vector<uint32_t> clone_display;
265 while (std::getline(i_value, i_clone_split_str, '+')) {
266 if (i_clone_split_str.empty() ||
267 i_clone_split_str.find_first_not_of("0123456789") !=
270 size_t i_clone_split_num = atoi(i_clone_split_str.c_str());
271 // Check and skip if the display already been used in other clone
272 bool skip_duplicate_display = false;
273 size_t clone_size = clone_duplicate_check.size();
274 for (size_t i = 0; i < clone_size; i++) {
275 if (clone_duplicate_check.at(i) == i_clone_split_num) {
276 skip_duplicate_display = true;
280 if (!skip_duplicate_display) {
281 // save the sub display num for the mosaic display (don't care
283 // the physical/logical display is existing/connected here)
284 clone_display.emplace_back(i_clone_split_num);
285 clone_duplicate_check.emplace_back(i_clone_split_num);
288 cloned_displays.emplace_back(clone_display);
289 } else if (!key.compare(key_physical_display_rotation)) {
290 std::string physical_index_str;
291 std::istringstream i_value(value);
292 // Got physical display index
293 std::getline(i_value, physical_index_str, ':');
294 if (physical_index_str.empty() ||
295 physical_index_str.find_first_not_of("0123456789") !=
299 uint32_t physical_index = atoi(physical_index_str.c_str());
300 // Check and skip if the display is already in use.
301 bool skip_duplicate_display = false;
302 size_t rotation_size = rotation_display_index.size();
303 for (size_t i = 0; i < rotation_size; i++) {
304 if (rotation_display_index.at(i) == physical_index) {
305 skip_duplicate_display = true;
310 if (skip_duplicate_display) {
314 std::string rotation_str;
316 std::getline(i_value, rotation_str, ':');
317 if (rotation_str.empty() ||
318 rotation_str.find_first_not_of("0123") != std::string::npos)
321 uint32_t rotation_num = atoi(rotation_str.c_str());
322 display_rotation.emplace_back(rotation_num);
323 rotation_display_index.emplace_back(physical_index);
324 } else if (!key.compare(key_float_display)) {
325 std::string index_str;
326 std::string float_rect_str;
327 std::vector<int32_t> float_rect;
328 std::istringstream i_value(value);
331 std::getline(i_value, index_str, ':');
332 if (index_str.empty() ||
333 index_str.find_first_not_of("0123456789") != std::string::npos) {
337 int32_t index = atoi(index_str.c_str());
339 // Got rectangle configuration
340 while (std::getline(i_value, float_rect_str, '+')) {
341 if (float_rect_str.empty() ||
342 float_rect_str.find_first_not_of("0123456789") !=
346 size_t float_rect_val = atoi(float_rect_str.c_str());
348 // Save the rectangle - left, top, right & bottom
349 float_rect.emplace_back(float_rect_val);
352 // If entire rect is available, store the parameters
353 // TODO remove hard code
354 if (float_rect.size() == 4) {
355 float_display_indices.emplace_back(index);
356 HwcRect<int32_t> rect =
357 HwcRect<int32_t>(float_rect.at(0), float_rect.at(1),
358 float_rect.at(2), float_rect.at(3));
359 float_displays.emplace_back(rect);
366 std::vector<NativeDisplay *> displays;
367 std::vector<NativeDisplay *> unordered_displays =
368 display_manager_->GetAllDisplays();
369 size_t size = unordered_displays.size();
370 uint32_t dispmgr_display_size = (uint32_t) size;
372 if (physical_displays.empty()) {
373 displays.swap(unordered_displays);
375 size = physical_displays.size();
376 for (size_t i = 0; i < size; i++) {
377 uint32_t pdisp_index = physical_displays.at(i);
378 // Add the physical display only if it has been enumerated from DRM API.
379 // Skip the non-existence display defined in hwc_display.ini file.
380 if (pdisp_index < dispmgr_display_size) {
381 displays.emplace_back(unordered_displays.at(pdisp_index));
384 "Physical display number: %u defined in hwc_display.ini "
385 "doesn't exist in enumerated DRM display list (total: %u).",
386 pdisp_index, dispmgr_display_size);
390 if (displays.size() != unordered_displays.size()) {
391 size = unordered_displays.size();
392 for (size_t i = 0; i < size; i++) {
393 NativeDisplay *display = unordered_displays.at(i);
394 uint32_t temp = displays.size();
395 for (size_t i = 0; i < temp; i++) {
396 if (displays.at(i) == display) {
403 displays.emplace_back(display);
409 // Re-order displays based on connection status.
410 std::vector<NativeDisplay *> connected_displays;
411 std::vector<NativeDisplay *> un_connected_displays;
412 size = displays.size();
413 for (size_t i = 0; i < size; i++) {
414 NativeDisplay *temp = displays.at(i);
415 if (temp->IsConnected()) {
416 connected_displays.emplace_back(temp);
418 un_connected_displays.emplace_back(temp);
422 displays.swap(connected_displays);
424 if (!un_connected_displays.empty()) {
425 size_t temp = un_connected_displays.size();
426 for (size_t i = 0; i < temp; i++) {
427 displays.emplace_back(un_connected_displays.at(i));
431 for (size_t i = 0; i < size; i++) {
432 displays.at(i)->SetDisplayOrder(i);
435 // We should have all displays ordered. Apply rotation settings.
436 if (rotate_display) {
437 size_t rotation_size = rotation_display_index.size();
438 for (size_t i = 0; i < rotation_size; i++) {
439 HWCRotation rotation = static_cast<HWCRotation>(display_rotation.at(i));
440 displays.at(rotation_display_index.at(i))->RotateDisplay(rotation);
444 // Now, we should have all physical displays ordered as required.
445 // Let's handle any Logical Display combinations or Mosaic.
446 std::vector<NativeDisplay *> temp_displays;
447 for (size_t i = 0; i < size; i++) {
448 hwcomposer::NativeDisplay *display = displays.at(i);
449 // Save logical displays to temp_displays, skip the physical display
450 if (use_logical && (logical_displays.size() >= i + 1) &&
451 logical_displays[i] > 1) {
452 std::unique_ptr<LogicalDisplayManager> manager(
453 new LogicalDisplayManager(display));
454 logical_display_manager_.emplace_back(std::move(manager));
455 // don't care if the displays is connected/disconnected here
456 logical_display_manager_.back()->InitializeLogicalDisplays(
457 logical_displays[i]);
458 std::vector<LogicalDisplay *> temp_logical_displays;
459 logical_display_manager_.back()->GetLogicalDisplays(
460 temp_logical_displays);
461 size_t logical_display_total_size = temp_logical_displays.size();
462 for (size_t j = 0; j < logical_display_total_size; j++) {
463 temp_displays.emplace_back(temp_logical_displays.at(j));
465 // Save no split physical displays to temp_displays
467 temp_displays.emplace_back(display);
471 std::vector<bool> available_displays(temp_displays.size(), true);
473 size_t displays_size = temp_displays.size();
474 for (size_t t = 0; t < displays_size; t++) {
475 // Skip the displays which already be marked in other mosaic
476 if (!available_displays.at(t))
478 bool skip_display = false;
479 size_t mosaic_size = mosaic_displays.size();
480 for (size_t m = 0; m < mosaic_size; m++) {
481 std::vector<NativeDisplay *> i_available_mosaic_displays;
482 size_t mosaic_inner_size = mosaic_displays.at(m).size();
483 for (size_t l = 0; l < mosaic_inner_size; l++) {
484 // Check if the logical display is in mosaic, keep the order of
485 // logical displays list
486 // Get the smallest logical num of the mosaic for order keeping
487 if (t == mosaic_displays.at(m).at(l)) {
488 // Loop to get logical displays of mosaic, keep the order of config
489 for (size_t i = 0; i < mosaic_inner_size; i++) {
490 // Verify the logical display num
491 if (mosaic_displays.at(m).at(i) < displays_size) {
492 // Skip the disconnected display here
493 i_available_mosaic_displays.emplace_back(
494 temp_displays.at(mosaic_displays.at(m).at(i)));
495 // Add tag for mosaic-ed displays
496 available_displays.at(mosaic_displays.at(m).at(i)) = false;
499 // Create mosaic for those logical displays
500 if (i_available_mosaic_displays.size() > 0) {
501 std::unique_ptr<MosaicDisplay> mosaic(
502 new MosaicDisplay(i_available_mosaic_displays));
503 mosaic_displays_.emplace_back(std::move(mosaic));
504 // Save the mosaic to the final displays list
505 total_displays_.emplace_back(mosaic_displays_.back().get());
515 total_displays_.emplace_back(temp_displays.at(t));
519 total_displays_.swap(temp_displays);
522 if (use_cloned && !use_mosaic && !use_logical) {
523 std::vector<NativeDisplay *> temp_displays;
524 size_t displays_size = total_displays_.size();
525 size_t cloned_displays_size = cloned_displays.size();
526 for (size_t c = 0; c < cloned_displays_size; c++) {
527 std::vector<uint32_t> &temp = cloned_displays.at(c);
528 size_t c_size = temp.size();
529 NativeDisplay *physical_display = total_displays_.at(temp.at(0));
530 for (size_t clone = 1; clone < c_size; clone++) {
531 total_displays_.at(temp.at(clone))->CloneDisplay(physical_display);
535 for (size_t t = 0; t < displays_size; t++) {
537 for (size_t c = 0; c < cloned_displays_size; c++) {
538 std::vector<uint32_t> &temp = cloned_displays.at(c);
539 size_t c_size = temp.size();
540 for (size_t clone = 1; clone < c_size; clone++) {
541 uint32_t temp_clone = temp.at(clone);
542 if (temp_clone == t) {
553 // Don't advertise cloned display as another independent
559 temp_displays.emplace_back(total_displays_.at(t));
562 temp_displays.swap(total_displays_);
565 // Now set floating display configuration
566 // Get the floating display index and the respective rectangle
567 // TODO Logical display on & mosaic display on scenario
568 if (use_float && !use_logical && !use_mosaic) {
570 size_t size = float_display_indices.size();
571 size_t num_displays = total_displays_.size();
573 // Set custom resolution to desired display instance
574 for (size_t i = 0; i < size; i++) {
575 int index = float_display_indices.at(i);
577 // Ignore float index if out of range of connected displays
578 if ((size_t)index < num_displays) {
579 const HwcRect<int32_t> &rect = float_displays.at(i);
580 ret = total_displays_.at(index)->SetCustomResolution(rect);
586 void GpuDevice::EnableHDCPSessionForDisplay(uint32_t display,
587 HWCContentType content_type) {
588 if (total_displays_.size() <= display) {
589 ETRACE("Tried to enable HDCP for invalid display %u \n", display);
593 NativeDisplay *native_display = total_displays_.at(display);
594 native_display->SetHDCPState(HWCContentProtection::kDesired, content_type);
597 void GpuDevice::EnableHDCPSessionForAllDisplays(HWCContentType content_type) {
598 size_t size = total_displays_.size();
599 for (size_t i = 0; i < size; i++) {
600 total_displays_.at(i)
601 ->SetHDCPState(HWCContentProtection::kDesired, content_type);
605 void GpuDevice::DisableHDCPSessionForDisplay(uint32_t display) {
606 if (total_displays_.size() <= display) {
607 ETRACE("Tried to enable HDCP for invalid display %u \n", display);
611 NativeDisplay *native_display = total_displays_.at(display);
612 native_display->SetHDCPState(HWCContentProtection::kUnDesired,
613 HWCContentType::kInvalid);
616 void GpuDevice::DisableHDCPSessionForAllDisplays() {
617 size_t size = total_displays_.size();
618 for (size_t i = 0; i < size; i++) {
619 total_displays_.at(i)->SetHDCPState(HWCContentProtection::kUnDesired,
620 HWCContentType::kInvalid);
624 void GpuDevice::SetPAVPSessionStatus(bool enabled, uint32_t pavp_session_id,
625 uint32_t pavp_instance_id) {
626 size_t size = total_displays_.size();
627 for (size_t i = 0; i < size; i++) {
628 total_displays_.at(i)->SetPAVPSessionStatus(enabled, pavp_session_id,
633 void GpuDevice::SetHDCPSRMForAllDisplays(const int8_t *SRM,
634 uint32_t SRMLength) {
635 size_t size = total_displays_.size();
636 for (size_t i = 0; i < size; i++) {
637 total_displays_.at(i)->SetHDCPSRM(SRM, SRMLength);
641 void GpuDevice::SetHDCPSRMForDisplay(uint32_t display, const int8_t *SRM,
642 uint32_t SRMLength) {
643 if (total_displays_.size() <= display) {
644 ETRACE("Tried to enable HDCP for invalid display %u \n", display);
648 NativeDisplay *native_display = total_displays_.at(display);
649 native_display->SetHDCPSRM(SRM, SRMLength);
652 void GpuDevice::HandleRoutine() {
653 bool update_ignored = false;
655 // Iniitialize resources to monitor external events.
656 // These can be two types:
657 // 1) We are showing splash screen and another App
658 // needs to take the control. In this case splash
660 // 2) Another app is having control of display and we
661 // we need to take control.
662 // TODO: Add splash screen support.
663 if (lock_fd_ != -1) {
664 display_manager_->IgnoreUpdates();
665 update_ignored = true;
667 if (flock(lock_fd_, LOCK_EX) != 0) {
668 ETRACE("Failed to wait on the hwc lock.");
670 ITRACE("Successfully grabbed the hwc lock.");
673 display_manager_->setDrmMaster();
680 display_manager_->ForceRefresh();
683 void GpuDevice::HandleWait() {
684 if (lock_fd_ == -1) {
685 HWCThread::HandleWait();
689 void GpuDevice::DisableWatch() {
693 } // namespace hwcomposer