X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=common%2Fcore%2Fgpudevice.cpp;h=170559d3269abdc08a277fb8d8181d5df0f9b3ee;hb=590e20d84d4f61b22a70163f78b3a8145ca166e9;hp=eaa53313eb9e46de6abb38793bf9fb5db793fde3;hpb=bcb0bd8c307ed301744f05cb49ab63b273e54167;p=android-x86%2Fexternal-IA-Hardware-Composer.git diff --git a/common/core/gpudevice.cpp b/common/core/gpudevice.cpp index eaa5331..170559d 100644 --- a/common/core/gpudevice.cpp +++ b/common/core/gpudevice.cpp @@ -16,11 +16,15 @@ #include +#include + #include "mosaicdisplay.h" +#include "hwctrace.h" + namespace hwcomposer { -GpuDevice::GpuDevice() : initialized_(false) { +GpuDevice::GpuDevice() : HWCThread(-8, "GpuDevice") { } GpuDevice::~GpuDevice() { @@ -28,40 +32,111 @@ GpuDevice::~GpuDevice() { } bool GpuDevice::Initialize() { - if (initialized_) + initialization_state_lock_.lock(); + if (initialization_state_ & kInitialized) { + initialization_state_lock_.unlock(); return true; + } - initialized_ = true; - display_manager_.reset(DisplayManager::CreateDisplayManager()); + initialization_state_ |= kInitialized; + initialization_state_lock_.unlock(); + + display_manager_.reset(DisplayManager::CreateDisplayManager(this)); bool success = display_manager_->Initialize(); if (!success) { return false; } - std::vector unordered_displays = - display_manager_->GetAllDisplays(); - size_t size = unordered_displays.size(); + display_manager_->InitializeDisplayResources(); + display_manager_->StartHotPlugMonitor(); - // Handle config file reading - const char *hwc_dp_cfg_path = std::getenv("HWC_DISPLAY_CONFIG"); - if (!hwc_dp_cfg_path) { - hwc_dp_cfg_path = "/vendor/etc/hwc_display.ini"; + HandleHWCSettings(); + + lock_fd_ = open("/vendor/hwc.lock", O_RDONLY); + if (-1 != lock_fd_) { + if (!InitWorker()) { + ETRACE("Failed to initalize thread for GpuDevice. %s", PRINTERROR()); + } + } else { + ITRACE("Failed to open " LOCK_DIR_PREFIX "/hwc.lock file!"); + } + + return true; +} + +uint32_t GpuDevice::GetFD() const { + return display_manager_->GetFD(); +} + +NativeDisplay *GpuDevice::GetDisplay(uint32_t display_id) { + if (total_displays_.size() > display_id) + return total_displays_.at(display_id); + + return NULL; +} + +NativeDisplay *GpuDevice::CreateVirtualDisplay(uint32_t display_index) { + return display_manager_->CreateVirtualDisplay(display_index); +} + +void GpuDevice::DestroyVirtualDisplay(uint32_t display_index) { + display_manager_->DestroyVirtualDisplay(display_index); +} + +void GpuDevice::GetConnectedPhysicalDisplays( + std::vector &displays) { + size_t size = total_displays_.size(); + for (size_t i = 0; i < size; i++) { + if (total_displays_.at(i)->IsConnected()) { + displays.emplace_back(total_displays_.at(i)); + } } +} + +const std::vector &GpuDevice::GetAllDisplays() { + return total_displays_; +} + +void GpuDevice::RegisterHotPlugEventCallback( + std::shared_ptr callback) { + display_manager_->RegisterHotPlugEventCallback(callback); +} + +void GpuDevice::HandleHWCSettings() { + // Handle config file reading + const char *hwc_dp_cfg_path = HWC_DISPLAY_INI_PATH; + ITRACE("Hwc display config file is %s", hwc_dp_cfg_path); bool use_logical = false; bool use_mosaic = false; + bool use_cloned = false; + bool rotate_display = false; + bool use_float = false; std::vector logical_displays; std::vector physical_displays; + std::vector display_rotation; + std::vector float_display_indices; + std::vector> float_displays; + std::vector> cloned_displays; std::vector> mosaic_displays; std::ifstream fin(hwc_dp_cfg_path); std::string cfg_line; std::string key_logical("LOGICAL"); std::string key_mosaic("MOSAIC"); + std::string key_clone("CLONE"); + std::string key_rotate("ROTATION"); + std::string key_float("FLOAT"); std::string key_logical_display("LOGICAL_DISPLAY"); std::string key_mosaic_display("MOSAIC_DISPLAY"); std::string key_physical_display("PHYSICAL_DISPLAY"); + std::string key_physical_display_rotation("PHYSICAL_DISPLAY_ROTATION"); + std::string key_clone_display("CLONE_DISPLAY"); + std::string key_float_display("FLOAT_DISPLAY"); std::vector mosaic_duplicate_check; + std::vector clone_duplicate_check; + std::vector physical_duplicate_check; + std::vector rotation_display_index; while (std::getline(fin, cfg_line)) { std::istringstream i_line(cfg_line); std::string key; @@ -86,7 +161,21 @@ bool GpuDevice::Initialize() { if (!value.compare(enable_str)) { use_mosaic = true; } - // Got logical config + // Got clone switch + } else if (!key.compare(key_clone)) { + if (!value.compare(enable_str)) { + use_cloned = true; + } + // Got rotation switch. + } else if (!key.compare(key_rotate)) { + if (!value.compare(enable_str)) { + rotate_display = true; + } + // Got float switch + } else if (!key.compare(key_float)) { + if (!value.compare(enable_str)) { + use_float = true; + } } else if (!key.compare(key_logical_display)) { std::string physical_index_str; std::istringstream i_value(value); @@ -128,13 +217,16 @@ bool GpuDevice::Initialize() { size_t i_mosaic_split_num = atoi(i_mosaic_split_str.c_str()); // Check and skip if the display already been used in other mosaic bool skip_duplicate_display = false; - for (size_t i = 0; i < mosaic_duplicate_check.size(); i++) { + size_t mosaic_size = mosaic_duplicate_check.size(); + for (size_t i = 0; i < mosaic_size; i++) { if (mosaic_duplicate_check.at(i) == i_mosaic_split_num) { skip_duplicate_display = true; + break; } } if (!skip_duplicate_display) { - // save the sub display num for the mosaic display (don't care if + // save the sub display num for the mosaic display (don't care + // if // the physical/logical display is existing/connected here) mosaic_display.emplace_back(i_mosaic_split_num); mosaic_duplicate_check.emplace_back(i_mosaic_split_num); @@ -144,7 +236,6 @@ bool GpuDevice::Initialize() { } else if (!key.compare(key_physical_display)) { std::istringstream i_value(value); std::string physical_split_str; - std::vector physical_duplicate_check; // Got physical display num while (std::getline(i_value, physical_split_str, ':')) { if (physical_split_str.empty() || @@ -154,30 +245,146 @@ bool GpuDevice::Initialize() { size_t physical_split_num = atoi(physical_split_str.c_str()); // Check and skip if the display already been used in other mosaic bool skip_duplicate_display = false; - for (size_t i = 0; i < physical_duplicate_check.size(); i++) { + size_t physical_size = physical_duplicate_check.size(); + for (size_t i = 0; i < physical_size; i++) { if (physical_duplicate_check.at(i) == physical_split_num) { skip_duplicate_display = true; + break; } } if (!skip_duplicate_display) { - if (physical_split_num < size) { - physical_displays.emplace_back(physical_split_num); - } + physical_displays.emplace_back(physical_split_num); physical_duplicate_check.emplace_back(physical_split_num); } } + } else if (!key.compare(key_clone_display)) { + std::istringstream i_value(value); + std::string i_clone_split_str; + // Got mosaic sub display num + std::vector clone_display; + while (std::getline(i_value, i_clone_split_str, '+')) { + if (i_clone_split_str.empty() || + i_clone_split_str.find_first_not_of("0123456789") != + std::string::npos) + continue; + size_t i_clone_split_num = atoi(i_clone_split_str.c_str()); + // Check and skip if the display already been used in other clone + bool skip_duplicate_display = false; + size_t clone_size = clone_duplicate_check.size(); + for (size_t i = 0; i < clone_size; i++) { + if (clone_duplicate_check.at(i) == i_clone_split_num) { + skip_duplicate_display = true; + break; + } + } + if (!skip_duplicate_display) { + // save the sub display num for the mosaic display (don't care + // if + // the physical/logical display is existing/connected here) + clone_display.emplace_back(i_clone_split_num); + clone_duplicate_check.emplace_back(i_clone_split_num); + } + } + cloned_displays.emplace_back(clone_display); + } else if (!key.compare(key_physical_display_rotation)) { + std::string physical_index_str; + std::istringstream i_value(value); + // Got physical display index + std::getline(i_value, physical_index_str, ':'); + if (physical_index_str.empty() || + physical_index_str.find_first_not_of("0123456789") != + std::string::npos) + continue; + + uint32_t physical_index = atoi(physical_index_str.c_str()); + // Check and skip if the display is already in use. + bool skip_duplicate_display = false; + size_t rotation_size = rotation_display_index.size(); + for (size_t i = 0; i < rotation_size; i++) { + if (rotation_display_index.at(i) == physical_index) { + skip_duplicate_display = true; + break; + } + } + + if (skip_duplicate_display) { + continue; + } + + std::string rotation_str; + // Got split num + std::getline(i_value, rotation_str, ':'); + if (rotation_str.empty() || + rotation_str.find_first_not_of("0123") != std::string::npos) + continue; + + uint32_t rotation_num = atoi(rotation_str.c_str()); + display_rotation.emplace_back(rotation_num); + rotation_display_index.emplace_back(physical_index); + } else if (!key.compare(key_float_display)) { + std::string index_str; + std::string float_rect_str; + std::vector float_rect; + std::istringstream i_value(value); + + // Got display index + std::getline(i_value, index_str, ':'); + if (index_str.empty() || + index_str.find_first_not_of("0123456789") != std::string::npos) { + continue; + } + + int32_t index = atoi(index_str.c_str()); + + // Got rectangle configuration + while (std::getline(i_value, float_rect_str, '+')) { + if (float_rect_str.empty() || + float_rect_str.find_first_not_of("0123456789") != + std::string::npos) { + continue; + } + size_t float_rect_val = atoi(float_rect_str.c_str()); + + // Save the rectangle - left, top, right & bottom + float_rect.emplace_back(float_rect_val); + } + + // If entire rect is available, store the parameters + // TODO remove hard code + if (float_rect.size() == 4) { + float_display_indices.emplace_back(index); + HwcRect rect = + HwcRect(float_rect.at(0), float_rect.at(1), + float_rect.at(2), float_rect.at(3)); + float_displays.emplace_back(rect); + } } } } }; std::vector displays; + std::vector unordered_displays = + display_manager_->GetAllDisplays(); + size_t size = unordered_displays.size(); + uint32_t dispmgr_display_size = (uint32_t) size; + if (physical_displays.empty()) { displays.swap(unordered_displays); } else { size = physical_displays.size(); for (size_t i = 0; i < size; i++) { - displays.emplace_back(unordered_displays.at(physical_displays.at(i))); + uint32_t pdisp_index = physical_displays.at(i); + // Add the physical display only if it has been enumerated from DRM API. + // Skip the non-existence display defined in hwc_display.ini file. + if (pdisp_index < dispmgr_display_size) { + displays.emplace_back(unordered_displays.at(pdisp_index)); + } else { + ETRACE( + "Physical display number: %u defined in hwc_display.ini " + "doesn't exist in enumerated DRM display list (total: %u).", + pdisp_index, dispmgr_display_size); + } } if (displays.size() != unordered_displays.size()) { @@ -199,11 +406,41 @@ bool GpuDevice::Initialize() { } } + // Re-order displays based on connection status. + std::vector connected_displays; + std::vector un_connected_displays; size = displays.size(); for (size_t i = 0; i < size; i++) { + NativeDisplay *temp = displays.at(i); + if (temp->IsConnected()) { + connected_displays.emplace_back(temp); + } else { + un_connected_displays.emplace_back(temp); + } + } + + displays.swap(connected_displays); + + if (!un_connected_displays.empty()) { + size_t temp = un_connected_displays.size(); + for (size_t i = 0; i < temp; i++) { + displays.emplace_back(un_connected_displays.at(i)); + } + } + + for (size_t i = 0; i < size; i++) { displays.at(i)->SetDisplayOrder(i); } + // We should have all displays ordered. Apply rotation settings. + if (rotate_display) { + size_t rotation_size = rotation_display_index.size(); + for (size_t i = 0; i < rotation_size; i++) { + HWCRotation rotation = static_cast(display_rotation.at(i)); + displays.at(rotation_display_index.at(i))->RotateDisplay(rotation); + } + } + // Now, we should have all physical displays ordered as required. // Let's handle any Logical Display combinations or Mosaic. std::vector temp_displays; @@ -233,22 +470,25 @@ bool GpuDevice::Initialize() { std::vector available_displays(temp_displays.size(), true); if (use_mosaic) { - for (size_t t = 0; t < temp_displays.size(); t++) { + size_t displays_size = temp_displays.size(); + for (size_t t = 0; t < displays_size; t++) { // Skip the displays which already be marked in other mosaic if (!available_displays.at(t)) continue; bool skip_display = false; - for (size_t m = 0; m < mosaic_displays.size(); m++) { + size_t mosaic_size = mosaic_displays.size(); + for (size_t m = 0; m < mosaic_size; m++) { std::vector i_available_mosaic_displays; - for (size_t l = 0; l < mosaic_displays.at(m).size(); l++) { + size_t mosaic_inner_size = mosaic_displays.at(m).size(); + for (size_t l = 0; l < mosaic_inner_size; l++) { // Check if the logical display is in mosaic, keep the order of // logical displays list // Get the smallest logical num of the mosaic for order keeping if (t == mosaic_displays.at(m).at(l)) { // Loop to get logical displays of mosaic, keep the order of config - for (size_t i = 0; i < mosaic_displays.at(m).size(); i++) { + for (size_t i = 0; i < mosaic_inner_size; i++) { // Verify the logical display num - if (mosaic_displays.at(m).at(i) < temp_displays.size()) { + if (mosaic_displays.at(m).at(i) < displays_size) { // Skip the disconnected display here i_available_mosaic_displays.emplace_back( temp_displays.at(mosaic_displays.at(m).at(i))); @@ -279,37 +519,175 @@ bool GpuDevice::Initialize() { total_displays_.swap(temp_displays); } - return true; + if (use_cloned && !use_mosaic && !use_logical) { + std::vector temp_displays; + size_t displays_size = total_displays_.size(); + size_t cloned_displays_size = cloned_displays.size(); + for (size_t c = 0; c < cloned_displays_size; c++) { + std::vector &temp = cloned_displays.at(c); + size_t c_size = temp.size(); + NativeDisplay *physical_display = total_displays_.at(temp.at(0)); + for (size_t clone = 1; clone < c_size; clone++) { + total_displays_.at(temp.at(clone))->CloneDisplay(physical_display); + } + } + + for (size_t t = 0; t < displays_size; t++) { + bool found = false; + for (size_t c = 0; c < cloned_displays_size; c++) { + std::vector &temp = cloned_displays.at(c); + size_t c_size = temp.size(); + for (size_t clone = 1; clone < c_size; clone++) { + uint32_t temp_clone = temp.at(clone); + if (temp_clone == t) { + found = true; + break; + } + } + + if (found) { + break; + } + } + + // Don't advertise cloned display as another independent + // Physical Display. + if (found) { + continue; + } + + temp_displays.emplace_back(total_displays_.at(t)); + } + + temp_displays.swap(total_displays_); + } + + // Now set floating display configuration + // Get the floating display index and the respective rectangle + // TODO Logical display on & mosaic display on scenario + if (use_float && !use_logical && !use_mosaic) { + bool ret = false; + size_t size = float_display_indices.size(); + size_t num_displays = total_displays_.size(); + + // Set custom resolution to desired display instance + for (size_t i = 0; i < size; i++) { + int index = float_display_indices.at(i); + + // Ignore float index if out of range of connected displays + if ((size_t)index < num_displays) { + const HwcRect &rect = float_displays.at(i); + ret = total_displays_.at(index)->SetCustomResolution(rect); + } + } + } } -NativeDisplay *GpuDevice::GetDisplay(uint32_t display_id) { - if (total_displays_.size() > display_id) - return total_displays_.at(display_id); +void GpuDevice::EnableHDCPSessionForDisplay(uint32_t display, + HWCContentType content_type) { + if (total_displays_.size() <= display) { + ETRACE("Tried to enable HDCP for invalid display %u \n", display); + return; + } - return NULL; + NativeDisplay *native_display = total_displays_.at(display); + native_display->SetHDCPState(HWCContentProtection::kDesired, content_type); } -NativeDisplay *GpuDevice::GetVirtualDisplay() { - return display_manager_->GetVirtualDisplay(); +void GpuDevice::EnableHDCPSessionForAllDisplays(HWCContentType content_type) { + size_t size = total_displays_.size(); + for (size_t i = 0; i < size; i++) { + total_displays_.at(i) + ->SetHDCPState(HWCContentProtection::kDesired, content_type); + } } -void GpuDevice::GetConnectedPhysicalDisplays( - std::vector &displays) { +void GpuDevice::DisableHDCPSessionForDisplay(uint32_t display) { + if (total_displays_.size() <= display) { + ETRACE("Tried to enable HDCP for invalid display %u \n", display); + return; + } + + NativeDisplay *native_display = total_displays_.at(display); + native_display->SetHDCPState(HWCContentProtection::kUnDesired, + HWCContentType::kInvalid); +} + +void GpuDevice::DisableHDCPSessionForAllDisplays() { size_t size = total_displays_.size(); for (size_t i = 0; i < size; i++) { - if (total_displays_.at(i)->IsConnected()) { - displays.emplace_back(total_displays_.at(i)); + total_displays_.at(i)->SetHDCPState(HWCContentProtection::kUnDesired, + HWCContentType::kInvalid); + } +} + +void GpuDevice::SetPAVPSessionStatus(bool enabled, uint32_t pavp_session_id, + uint32_t pavp_instance_id) { + size_t size = total_displays_.size(); + for (size_t i = 0; i < size; i++) { + total_displays_.at(i)->SetPAVPSessionStatus(enabled, pavp_session_id, + pavp_instance_id); + } +} + +void GpuDevice::SetHDCPSRMForAllDisplays(const int8_t *SRM, + uint32_t SRMLength) { + size_t size = total_displays_.size(); + for (size_t i = 0; i < size; i++) { + total_displays_.at(i)->SetHDCPSRM(SRM, SRMLength); + } +} + +void GpuDevice::SetHDCPSRMForDisplay(uint32_t display, const int8_t *SRM, + uint32_t SRMLength) { + if (total_displays_.size() <= display) { + ETRACE("Tried to enable HDCP for invalid display %u \n", display); + return; + } + + NativeDisplay *native_display = total_displays_.at(display); + native_display->SetHDCPSRM(SRM, SRMLength); +} + +void GpuDevice::HandleRoutine() { + bool update_ignored = false; + + // Iniitialize resources to monitor external events. + // These can be two types: + // 1) We are showing splash screen and another App + // needs to take the control. In this case splash + // is true. + // 2) Another app is having control of display and we + // we need to take control. + // TODO: Add splash screen support. + if (lock_fd_ != -1) { + display_manager_->IgnoreUpdates(); + update_ignored = true; + + if (flock(lock_fd_, LOCK_EX) != 0) { + ETRACE("Failed to wait on the hwc lock."); + } else { + ITRACE("Successfully grabbed the hwc lock."); } + + display_manager_->setDrmMaster(); + + close(lock_fd_); + lock_fd_ = -1; } + + if (update_ignored) + display_manager_->ForceRefresh(); } -std::vector GpuDevice::GetAllDisplays() { - return total_displays_; +void GpuDevice::HandleWait() { + if (lock_fd_ == -1) { + HWCThread::HandleWait(); + } } -void GpuDevice::RegisterHotPlugEventCallback( - std::shared_ptr callback) { - display_manager_->RegisterHotPlugEventCallback(callback); +void GpuDevice::DisableWatch() { + HWCThread::Exit(); } } // namespace hwcomposer