OSDN Git Service

Update GPUDevice thread for DRM-master setting/dropping
authorShaofeng Tang <shaofeng.tang@intel.com>
Wed, 3 Apr 2019 05:27:16 +0000 (13:27 +0800)
committerShaofeng Tang <shaofeng.tang@intel.com>
Thu, 4 Apr 2019 06:03:44 +0000 (14:03 +0800)
GPUDevice thread will monitor hwc.lock once HWC is not drm master
Drm Master will not be set once hwc.lock is not available.

On Acrn and Celadon, an additional selinux patch are needed for
the permission on hwc.lock.

Change-Id: If185b7f1b912dd58ffcb0287fe1b3a234afc5b57
Test: Compile sucessful for Android.
Tracked-On: https://jira.devtools.intel.com/browse/OAM-76578
Signed-off-by: Shaofeng Tang <shaofeng.tang@intel.com>
common/core/gpudevice.cpp
common/core/logicaldisplay.cpp
common/core/logicaldisplay.h
common/core/mosaicdisplay.cpp
common/core/mosaicdisplay.h
public/gpudevice.h
wsi/displaymanager.h
wsi/drm/drmdisplaymanager.cpp
wsi/drm/drmdisplaymanager.h

index b20c128..4d6808b 100644 (file)
@@ -29,6 +29,21 @@ GpuDevice::GpuDevice() : HWCThread(-8, "GpuDevice") {
 
 GpuDevice::~GpuDevice() {
   display_manager_.reset(nullptr);
+  HWCThread::Exit();
+
+  if (-1 != lock_fd_) {
+    close(lock_fd_);
+    lock_fd_ = -1;
+  }
+}
+
+void GpuDevice::ResetAllDisplayCommit(bool enable) {
+  if (enable == enable_all_display_)
+    return;
+  enable_all_display_ = enable;
+  size_t size = total_displays_.size();
+  for (size_t i = 0; i < size; i++)
+    total_displays_.at(i)->EnableDRMCommit(enable);
 }
 
 bool GpuDevice::Initialize() {
@@ -57,13 +72,19 @@ bool GpuDevice::Initialize() {
     display_manager_->RemoveUnreservedPlanes();
   }
 
-  lock_fd_ = open("/vendor/hwc.lock", O_RDONLY);
+  // Ignore all updates by default
+  ResetAllDisplayCommit(false);
+  lock_fd_ = open(HWC_LOCK_FILE, 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!");
+    ETRACE("Failed to open %s", HWC_LOCK_FILE);
+    // HWC should become drm master and start to commit.
+    // if hwc.lock is not available
+    display_manager_->setDrmMaster(true);
+    ResetAllDisplayCommit(true);
   }
 
   return true;
@@ -103,7 +124,6 @@ void GpuDevice::GetConnectedPhysicalDisplays(
 }
 
 bool GpuDevice::EnableDRMCommit(bool enable, uint32_t display_id) {
-  // TODO clean all display for commit status
   size_t size = total_displays_.size();
   bool ret = false;
   if (size > display_id)
@@ -111,6 +131,35 @@ bool GpuDevice::EnableDRMCommit(bool enable, uint32_t display_id) {
   return ret;
 }
 
+bool GpuDevice::ResetDrmMaster(bool drop_master) {
+  bool ret = true;
+  if (drop_master) {
+    ResetAllDisplayCommit(false);
+    display_manager_->DropDrmMaster();
+    ITRACE("locking %s and monitoring if %s is unlocked.", HWC_LOCK_FILE,
+           HWC_LOCK_FILE);
+    // Resume GpuDevice thread to check hwc.lock and re-apply drm master.
+    lock_fd_ = open(HWC_LOCK_FILE, O_RDONLY);
+    if (-1 != lock_fd_) {
+      // Only resume GpuDevice thread for dropping DRM Master and
+      // the lock file exist.
+      Resume();
+      return !display_manager_->IsDrmMaster();
+    }
+  }
+  // In case of setDrmMaster or the lock file is not exist.
+  // Re-set DRM Master true.
+  display_manager_->setDrmMaster(false);
+  ResetAllDisplayCommit(true);
+  DisableWatch();
+
+  if (drop_master)
+    ret = !display_manager_->IsDrmMaster();
+  else
+    ret = display_manager_->IsDrmMaster();
+  return ret;
+}
+
 const std::vector<NativeDisplay *> &GpuDevice::GetAllDisplays() {
   return total_displays_;
 }
@@ -967,8 +1016,6 @@ uint32_t GpuDevice::GetDisplayIDFromConnectorID(const uint32_t connector_id) {
 }
 
 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
@@ -978,23 +1025,20 @@ void GpuDevice::HandleRoutine() {
   //    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.");
+      ITRACE("Fail to grab the hwc lock.");
     } else {
       ITRACE("Successfully grabbed the hwc lock.");
+      // Set DRM master
+      if (!display_manager_->IsDrmMaster())
+        display_manager_->setDrmMaster(true);
+      // stop ignoring and force refresh
+      ResetAllDisplayCommit(true);
+      flock(lock_fd_, LOCK_UN);
+      close(lock_fd_);
+      lock_fd_ = -1;
     }
-
-    display_manager_->setDrmMaster();
-
-    close(lock_fd_);
-    lock_fd_ = -1;
   }
-
-  if (update_ignored)
-    display_manager_->ForceRefresh();
 }
 
 void GpuDevice::HandleWait() {
@@ -1004,7 +1048,10 @@ void GpuDevice::HandleWait() {
 }
 
 void GpuDevice::DisableWatch() {
-  HWCThread::Exit();
+  if (lock_fd_ != -1) {
+    close(lock_fd_);
+    lock_fd_ = -1;
+  }
 }
 
 GpuDevice &GpuDevice::getInstance() {
index 053a995..aafb163 100644 (file)
@@ -51,6 +51,10 @@ int LogicalDisplay::GetDisplayPipe() {
   return physical_display_->GetDisplayPipe();
 }
 
+bool LogicalDisplay::EnableDRMCommit(bool enable) {
+  return physical_display_->EnableDRMCommit(enable);
+}
+
 bool LogicalDisplay::SetActiveConfig(uint32_t config) {
   bool success = physical_display_->SetActiveConfig(config);
   width_ = (physical_display_->Width()) / total_divisions_;
index 33c8a62..2c66f42 100644 (file)
@@ -103,6 +103,8 @@ class LogicalDisplay : public NativeDisplay {
   bool GetDisplayConfigs(uint32_t *num_configs, uint32_t *configs) override;
   bool GetDisplayName(uint32_t *size, char *name) override;
 
+  bool EnableDRMCommit(bool enable) override;
+
   uint32_t GetXTranslation() override {
     return (((physical_display_->Width()) / total_divisions_) * index_);
   }
index a969d48..d16328c 100644 (file)
@@ -110,6 +110,13 @@ int MosaicDisplay::GetDisplayPipe() {
   return physical_displays_.at(0)->GetDisplayPipe();
 }
 
+bool MosaicDisplay::EnableDRMCommit(bool enable) {
+  uint32_t size = physical_displays_.size();
+  for (uint32_t i = 0; i < size; i++)
+    physical_displays_.at(i)->EnableDRMCommit(enable);
+  return true;
+}
+
 bool MosaicDisplay::SetActiveConfig(uint32_t config) {
   config_ = config;
   width_ = 0;
index 4930d2f..302e79b 100644 (file)
@@ -94,6 +94,8 @@ class MosaicDisplay : public NativeDisplay {
   bool GetDisplayConfigs(uint32_t *num_configs, uint32_t *configs) override;
   bool GetDisplayName(uint32_t *size, char *name) override;
 
+  bool EnableDRMCommit(bool enable) override;
+
   uint32_t GetXTranslation() override {
     return 0;
   }
index 8d4b833..2f9d519 100644 (file)
 #ifndef PUBLIC_GPUDEVICE_H_
 #define PUBLIC_GPUDEVICE_H_
 
+#ifndef HWC_LOCK_FILE
+#define HWC_LOCK_FILE "/vendor/hwc.lock"
+#endif
+
 #include <stdint.h>
 #include <fstream>
 #include <sstream>
@@ -97,11 +101,15 @@ class GpuDevice : public HWCThread {
 
   bool EnableDRMCommit(bool enable, uint32_t display_id);
 
+  bool ResetDrmMaster(bool drop_master);
+
   std::vector<uint32_t> GetDisplayReservedPlanes(uint32_t display_id);
 
  private:
   GpuDevice();
 
+  void ResetAllDisplayCommit(bool enable);
+
   enum InitializationType {
     kUnInitialized = 0,    // Nothing Initialized.
     kInitialized = 1 << 1  // Everything Initialized
@@ -168,9 +176,11 @@ class GpuDevice : public HWCThread {
   std::vector<NativeDisplay*> total_displays_;
 
   bool reserve_plane_ = false;
+  bool enable_all_display_ = true;
   std::map<uint8_t, std::vector<uint32_t>> reserved_drm_display_planes_map_;
   uint32_t initialization_state_ = kUnInitialized;
   SpinLock initialization_state_lock_;
+  SpinLock drm_master_lock_;
   int lock_fd_ = -1;
   friend class DrmDisplayManager;
 };
index a73b20c..3ed0542 100644 (file)
@@ -53,7 +53,11 @@ class DisplayManager {
   // manager until ForceRefresh is called.
   virtual void IgnoreUpdates() = 0;
 
-  virtual void setDrmMaster() = 0;
+  virtual void setDrmMaster(bool must_set) = 0;
+
+  virtual void DropDrmMaster() = 0;
+
+  virtual bool IsDrmMaster() = 0;
 
   // Get FD associated with this DisplayManager.
   virtual uint32_t GetFD() const = 0;
index c1aac7d..7a059af 100644 (file)
@@ -45,6 +45,7 @@ DrmDisplayManager::DrmDisplayManager() : HWCThread(-8, "DisplayManager") {
 DrmDisplayManager::~DrmDisplayManager() {
   CTRACE();
   std::vector<std::unique_ptr<DrmDisplay>>().swap(displays_);
+
 #ifndef DISABLE_HOTPLUG_NOTIFICATION
   close(hotplug_fd_);
 #endif
@@ -112,6 +113,7 @@ bool DrmDisplayManager::Initialize() {
 
   fd_handler_.AddFd(hotplug_fd_);
 #endif
+
   IHOTPLUGEVENTTRACE("DisplayManager Initialization succeeded.");
   return true;
 }
@@ -442,15 +444,49 @@ void DrmDisplayManager::IgnoreUpdates() {
   }
 }
 
-void DrmDisplayManager::setDrmMaster() {
-  int ret = drmSetMaster(fd_);
-  while (ret) {
-    usleep(10000);
+void DrmDisplayManager::setDrmMaster(bool must_set) {
+  spin_lock_.lock();
+  if (drm_master_) {
+    spin_lock_.unlock();
+    return;
+  }
+  int ret = 0;
+  uint8_t retry_times = 0;
+  do {
     ret = drmSetMaster(fd_);
+    if (!must_set)
+      retry_times++;
     if (ret) {
       ETRACE("Failed to call drmSetMaster : %s", PRINTERROR());
+      usleep(10000);
+    } else {
+      ITRACE("Successfully set as DRM master.");
+      drm_master_ = true;
     }
+  } while (ret && retry_times < 10);
+  spin_lock_.unlock();
+}
+
+void DrmDisplayManager::DropDrmMaster() {
+  spin_lock_.lock();
+  if (!drm_master_) {
+    spin_lock_.unlock();
+    return;
   }
+  int ret = 0;
+  uint8_t retry_times = 0;
+  do {
+    ret = drmDropMaster(fd_);
+    retry_times++;
+    if (ret) {
+      ETRACE("Failed to call drmDropMaster : %s", PRINTERROR());
+      usleep(10000);
+    } else {
+      ITRACE("Successfully drop DRM master.");
+      drm_master_ = false;
+    }
+  } while (ret && retry_times < 10);
+  spin_lock_.unlock();
 }
 
 void DrmDisplayManager::HandleLazyInitialization() {
index 0b051e3..1b95f51 100644 (file)
@@ -71,7 +71,13 @@ class DrmDisplayManager : public HWCThread, public DisplayManager {
 
   void IgnoreUpdates() override;
 
-  void setDrmMaster() override;
+  void setDrmMaster(bool must_set) override;
+
+  void DropDrmMaster() override;
+
+  bool IsDrmMaster() override {
+    return drm_master_;
+  }
 
   uint32_t GetFD() const override {
     return fd_;
@@ -115,6 +121,7 @@ class DrmDisplayManager : public HWCThread, public DisplayManager {
   bool release_lock_ = false;
   SpinLock spin_lock_;
   int connected_display_count_ = 0;
+  bool drm_master_ = false;
 };
 
 }  // namespace hwcomposer