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() {
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;
}
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)
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_;
}
}
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
// 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() {
}
void GpuDevice::DisableWatch() {
- HWCThread::Exit();
+ if (lock_fd_ != -1) {
+ close(lock_fd_);
+ lock_fd_ = -1;
+ }
}
GpuDevice &GpuDevice::getInstance() {
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_;
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_);
}
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;
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;
}
#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>
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
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;
};
// 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;
DrmDisplayManager::~DrmDisplayManager() {
CTRACE();
std::vector<std::unique_ptr<DrmDisplay>>().swap(displays_);
+
#ifndef DISABLE_HOTPLUG_NOTIFICATION
close(hotplug_fd_);
#endif
fd_handler_.AddFd(hotplug_fd_);
#endif
+
IHOTPLUGEVENTTRACE("DisplayManager Initialization succeeded.");
return true;
}
}
}
-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() {
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_;
bool release_lock_ = false;
SpinLock spin_lock_;
int connected_display_count_ = 0;
+ bool drm_master_ = false;
};
} // namespace hwcomposer