Respect libdrm vsyncs am: 377ff8cf97
Original change: https://android-review.googlesource.com/c/device/generic/goldfish-opengl/+/1959651
Change-Id: I7de1bf21a1a52506c3376e724bf6154771872593
diff --git a/system/hwc2/Composer.h b/system/hwc2/Composer.h
index a0bdb82..0c47eab 100644
--- a/system/hwc2/Composer.h
+++ b/system/hwc2/Composer.h
@@ -38,7 +38,7 @@
uint32_t /*height*/, uint32_t /*dpiX*/, uint32_t /*dpiY*/,
uint32_t /*refreshRate*/)>;
- virtual HWC2::Error init(const HotplugCallback& cb) = 0;
+ virtual HWC2::Error init() = 0;
virtual HWC2::Error onDisplayCreate(Display* display) = 0;
diff --git a/system/hwc2/Device.cpp b/system/hwc2/Device.cpp
index eaf8bba..b427f60 100644
--- a/system/hwc2/Device.cpp
+++ b/system/hwc2/Device.cpp
@@ -25,6 +25,21 @@
namespace android {
namespace {
+static bool isMinigbmFromProperty() {
+ static constexpr const auto kGrallocProp = "ro.hardware.gralloc";
+
+ const auto grallocProp = android::base::GetProperty(kGrallocProp, "");
+ DEBUG_LOG("%s: prop value is: %s", __FUNCTION__, grallocProp.c_str());
+
+ if (grallocProp == "minigbm") {
+ ALOGD("%s: Using minigbm, in minigbm mode.\n", __FUNCTION__);
+ return true;
+ } else {
+ ALOGD("%s: Is not using minigbm, in goldfish mode.\n", __FUNCTION__);
+ return false;
+ }
+}
+
template <typename PFN, typename T>
static hwc2_function_pointer_t asFP(T function) {
static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
@@ -51,22 +66,33 @@
common.close = CloseHook;
hwc2_device_t::getCapabilities = getCapabilitiesHook;
hwc2_device_t::getFunction = getFunctionHook;
+
+ mDrmPresenter = std::make_unique<DrmPresenter>();
}
HWC2::Error Device::init() {
DEBUG_LOG("%s", __FUNCTION__);
-
+ bool isMinigbm = isMinigbmFromProperty();
if (ShouldUseGuestComposer()) {
- mComposer = std::make_unique<GuestComposer>();
+ mComposer = std::make_unique<GuestComposer>(mDrmPresenter.get());
} else {
- mComposer = std::make_unique<HostComposer>();
+ mComposer = std::make_unique<HostComposer>(mDrmPresenter.get(), isMinigbm);
}
- HWC2::Error error = mComposer->init(
- [this](bool connected, uint32_t id, uint32_t width, uint32_t height,
- uint32_t dpiX, uint32_t dpiY, uint32_t refreshRate) {
- handleHotplug(connected, id, width, height, dpiX, dpiY, refreshRate);
- });
+ if (ShouldUseGuestComposer() || isMinigbm) {
+ bool success = mDrmPresenter->init(
+ [this](bool connected, uint32_t id, uint32_t width, uint32_t height,
+ uint32_t dpiX, uint32_t dpiY, uint32_t refreshRate) {
+ handleHotplug(connected, id, width, height, dpiX, dpiY, refreshRate);
+ });
+
+ if (!success) {
+ ALOGE("%s: failed to initialize DrmPresenter", __FUNCTION__);
+ return HWC2::Error::NoResources;
+ }
+ }
+
+ HWC2::Error error = mComposer->init();
if (error != HWC2::Error::None) {
ALOGE("%s failed to initialize Composer", __FUNCTION__);
@@ -99,7 +125,7 @@
std::vector<DisplayMultiConfigs> displays;
- HWC2::Error error = findDisplays(displays);
+ HWC2::Error error = findDisplays(mDrmPresenter.get(), displays);
if (error != HWC2::Error::None) {
ALOGE("%s failed to find display configs", __FUNCTION__);
return error;
diff --git a/system/hwc2/Device.h b/system/hwc2/Device.h
index 812d5e9..7361d3a 100644
--- a/system/hwc2/Device.h
+++ b/system/hwc2/Device.h
@@ -29,6 +29,7 @@
#include "Common.h"
#include "Composer.h"
#include "Display.h"
+#include "DrmPresenter.h"
#include "Layer.h"
namespace android {
@@ -144,8 +145,9 @@
hwc2_function_pointer_t pointer;
};
std::unordered_map<HWC2::Callback, CallbackInfo> mCallbacks;
-
std::map<hwc2_display_t, std::unique_ptr<Display>> mDisplays;
+
+ std::unique_ptr<DrmPresenter> mDrmPresenter;
};
} // namespace android
diff --git a/system/hwc2/DisplayConfig.h b/system/hwc2/DisplayConfig.h
index 67e4c49..02d9b77 100644
--- a/system/hwc2/DisplayConfig.h
+++ b/system/hwc2/DisplayConfig.h
@@ -84,4 +84,4 @@
int32_t mConfigGroup;
};
-#endif
\ No newline at end of file
+#endif
diff --git a/system/hwc2/DisplayFinder.cpp b/system/hwc2/DisplayFinder.cpp
index df8f0fd..5fb192b 100644
--- a/system/hwc2/DisplayFinder.cpp
+++ b/system/hwc2/DisplayFinder.cpp
@@ -31,6 +31,30 @@
return 1000 * 1000 * 1000 / hertz;
}
+static int getVsyncHzFromProperty() {
+ static constexpr const auto kVsyncProp = "ro.boot.qemu.vsync";
+
+ const auto vsyncProp = android::base::GetProperty(kVsyncProp, "");
+ DEBUG_LOG("%s: prop value is: %s", __FUNCTION__, vsyncProp.c_str());
+
+ uint64_t vsyncPeriod;
+ if (!android::base::ParseUint(vsyncProp, &vsyncPeriod)) {
+ ALOGE("%s: failed to parse vsync period '%s', returning default 60",
+ __FUNCTION__, vsyncProp.c_str());
+ return 60;
+ }
+
+ return static_cast<int>(vsyncPeriod);
+}
+
+int32_t getVsyncForDisplay(DrmPresenter* drmPresenter,
+ uint32_t displayId) {
+ const int32_t vsyncPeriodForDisplay = drmPresenter->refreshRate(displayId);
+ return vsyncPeriodForDisplay < 0 ?
+ HertzToPeriodNanos(getVsyncHzFromProperty()) :
+ HertzToPeriodNanos(vsyncPeriodForDisplay);
+}
+
HWC2::Error findCuttlefishDisplays(std::vector<DisplayMultiConfigs>& displays) {
DEBUG_LOG("%s", __FUNCTION__);
@@ -39,6 +63,8 @@
hwc2_display_t displayId = 0;
for (const auto& deviceDisplayConfig : deviceConfig.display_config()) {
+ // crosvm does not fully support EDID yet, so we solely rely on the
+ // device config for our vsync.
const auto vsyncPeriodNanos =
HertzToPeriodNanos(deviceDisplayConfig.refresh_rate_hz());
@@ -62,29 +88,13 @@
return HWC2::Error::None;
}
-static int getVsyncHzFromProperty() {
- static constexpr const auto kVsyncProp = "ro.boot.qemu.vsync";
-
- const auto vsyncProp = android::base::GetProperty(kVsyncProp, "");
- DEBUG_LOG("%s: prop value is: %s", __FUNCTION__, vsyncProp.c_str());
-
- uint64_t vsyncPeriod;
- if (!android::base::ParseUint(vsyncProp, &vsyncPeriod)) {
- ALOGE("%s: failed to parse vsync period '%s', returning default 60",
- __FUNCTION__, vsyncProp.c_str());
- return 60;
- }
-
- return static_cast<int>(vsyncPeriod);
-}
-
HWC2::Error findGoldfishPrimaryDisplay(
+ DrmPresenter* drmPresenter,
std::vector<DisplayMultiConfigs>& displays) {
DEBUG_LOG("%s", __FUNCTION__);
DEFINE_AND_VALIDATE_HOST_CONNECTION
hostCon->lock();
- const int32_t vsyncPeriodNanos = HertzToPeriodNanos(getVsyncHzFromProperty());
DisplayMultiConfigs display;
display.displayId = 0;
if (rcEnc->hasHWCMultiConfigs()) {
@@ -102,7 +112,7 @@
rcEnc->rcGetFBDisplayConfigsParam(rcEnc, configId, FB_HEIGHT), //
rcEnc->rcGetFBDisplayConfigsParam(rcEnc, configId, FB_XDPI), //
rcEnc->rcGetFBDisplayConfigsParam(rcEnc, configId, FB_YDPI), //
- vsyncPeriodNanos //
+ getVsyncForDisplay(drmPresenter, configId) //
));
}
} else {
@@ -113,7 +123,7 @@
rcEnc->rcGetFBParam(rcEnc, FB_HEIGHT), //
rcEnc->rcGetFBParam(rcEnc, FB_XDPI), //
rcEnc->rcGetFBParam(rcEnc, FB_YDPI), //
- vsyncPeriodNanos //
+ getVsyncForDisplay(drmPresenter, 0) //
));
}
hostCon->unlock();
@@ -179,8 +189,9 @@
return HWC2::Error::None;
}
-HWC2::Error findGoldfishDisplays(std::vector<DisplayMultiConfigs>& displays) {
- HWC2::Error error = findGoldfishPrimaryDisplay(displays);
+HWC2::Error findGoldfishDisplays(DrmPresenter* drmPresenter,
+ std::vector<DisplayMultiConfigs>& displays) {
+ HWC2::Error error = findGoldfishPrimaryDisplay(drmPresenter, displays);
if (error != HWC2::Error::None) {
ALOGE("%s failed to find Goldfish primary display", __FUNCTION__);
return error;
@@ -196,12 +207,13 @@
} // namespace
-HWC2::Error findDisplays(std::vector<DisplayMultiConfigs>& displays) {
+HWC2::Error findDisplays(DrmPresenter* drmPresenter,
+ std::vector<DisplayMultiConfigs>& displays) {
HWC2::Error error = HWC2::Error::None;
if (IsCuttlefish()) {
error = findCuttlefishDisplays(displays);
} else {
- error = findGoldfishDisplays(displays);
+ error = findGoldfishDisplays(drmPresenter, displays);
}
if (error != HWC2::Error::None) {
diff --git a/system/hwc2/DisplayFinder.h b/system/hwc2/DisplayFinder.h
index b9e1b19..5f22172 100644
--- a/system/hwc2/DisplayFinder.h
+++ b/system/hwc2/DisplayFinder.h
@@ -21,6 +21,7 @@
#include "Common.h"
#include "DisplayConfig.h"
+#include "DrmPresenter.h"
namespace android {
@@ -31,7 +32,8 @@
std::vector<DisplayConfig> configs;
};
-HWC2::Error findDisplays(std::vector<DisplayMultiConfigs>& displays);
+HWC2::Error findDisplays(DrmPresenter* drmPresenter,
+ std::vector<DisplayMultiConfigs>& displays);
} // namespace android
diff --git a/system/hwc2/DrmPresenter.cpp b/system/hwc2/DrmPresenter.cpp
index f1cbe48..b805749 100644
--- a/system/hwc2/DrmPresenter.cpp
+++ b/system/hwc2/DrmPresenter.cpp
@@ -530,14 +530,15 @@
return edid;
}
-DrmBuffer::DrmBuffer(const native_handle_t* handle, DrmPresenter& DrmPresenter)
- : mDrmPresenter(DrmPresenter), mBo({}) {
+DrmBuffer::DrmBuffer(const native_handle_t* handle,
+ DrmPresenter* drmPresenter)
+ : mDrmPresenter(drmPresenter), mBo({}) {
if (!convertBoInfo(handle)) {
- mDrmPresenter.getDrmFB(mBo);
+ mDrmPresenter->getDrmFB(mBo);
}
}
-DrmBuffer::~DrmBuffer() { mDrmPresenter.clearDrmFB(mBo); }
+DrmBuffer::~DrmBuffer() { mDrmPresenter->clearDrmFB(mBo); }
int DrmBuffer::convertBoInfo(const native_handle_t* handle) {
cros_gralloc_handle* gr_handle = (cros_gralloc_handle*)handle;
@@ -557,7 +558,7 @@
std::tuple<HWC2::Error, base::unique_fd> DrmBuffer::flushToDisplay(
int display, base::borrowed_fd inWaitSyncFd) {
- return mDrmPresenter.flushToDisplay(display, mBo, inWaitSyncFd);
+ return mDrmPresenter->flushToDisplay(display, mBo, inWaitSyncFd);
}
DrmPresenter::DrmEventListener::DrmEventListener(DrmPresenter& presenter)
diff --git a/system/hwc2/DrmPresenter.h b/system/hwc2/DrmPresenter.h
index aec71eb..fdf06b7 100644
--- a/system/hwc2/DrmPresenter.h
+++ b/system/hwc2/DrmPresenter.h
@@ -40,7 +40,8 @@
// A RAII object that will clear a drm framebuffer upon destruction.
class DrmBuffer {
public:
- DrmBuffer(const native_handle_t* handle, DrmPresenter& drmPresenter);
+ DrmBuffer(const native_handle_t* handle,
+ DrmPresenter* drmPresenter);
~DrmBuffer();
DrmBuffer(const DrmBuffer&) = delete;
@@ -55,7 +56,7 @@
private:
int convertBoInfo(const native_handle_t* handle);
- DrmPresenter& mDrmPresenter;
+ DrmPresenter* mDrmPresenter;
hwc_drm_bo_t mBo;
};
@@ -77,7 +78,13 @@
bool init(const HotplugCallback& cb);
- uint32_t refreshRate() const { return mConnectors[0].mRefreshRateAsInteger; }
+ uint32_t refreshRate(uint32_t display) const {
+ if (display < mConnectors.size()) {
+ return mConnectors[display].mRefreshRateAsInteger;
+ }
+
+ return -1;
+ }
std::tuple<HWC2::Error, base::unique_fd> flushToDisplay(
int display, hwc_drm_bo_t& fb, base::borrowed_fd inWaitSyncFd);
diff --git a/system/hwc2/GuestComposer.cpp b/system/hwc2/GuestComposer.cpp
index f1bdfe6..1bfaaea 100644
--- a/system/hwc2/GuestComposer.cpp
+++ b/system/hwc2/GuestComposer.cpp
@@ -398,14 +398,11 @@
} // namespace
-HWC2::Error GuestComposer::init(const HotplugCallback& cb) {
+GuestComposer::GuestComposer(DrmPresenter* drmPresenter) :
+ mDrmPresenter(drmPresenter) {}
+
+HWC2::Error GuestComposer::init() {
DEBUG_LOG("%s", __FUNCTION__);
-
- if (!mDrmPresenter.init(cb)) {
- ALOGE("%s: failed to initialize DrmPresenter", __FUNCTION__);
- return HWC2::Error::NoResources;
- }
-
return HWC2::Error::None;
}
diff --git a/system/hwc2/GuestComposer.h b/system/hwc2/GuestComposer.h
index bf2084f..a7a8be7 100644
--- a/system/hwc2/GuestComposer.h
+++ b/system/hwc2/GuestComposer.h
@@ -28,7 +28,7 @@
class GuestComposer : public Composer {
public:
- GuestComposer() = default;
+ GuestComposer(DrmPresenter* drmPresenter);
GuestComposer(const GuestComposer&) = delete;
GuestComposer& operator=(const GuestComposer&) = delete;
@@ -36,7 +36,7 @@
GuestComposer(GuestComposer&&) = delete;
GuestComposer& operator=(GuestComposer&&) = delete;
- HWC2::Error init(const HotplugCallback& cb) override;
+ HWC2::Error init() override;
HWC2::Error onDisplayCreate(Display*) override;
@@ -97,7 +97,7 @@
Gralloc mGralloc;
- DrmPresenter mDrmPresenter;
+ DrmPresenter* mDrmPresenter;
// Cuttlefish on QEMU does not have a display. Disable presenting to avoid
// spamming logcat with DRM commit failures.
diff --git a/system/hwc2/HostComposer.cpp b/system/hwc2/HostComposer.cpp
index fd9021c..73d717d 100644
--- a/system/hwc2/HostComposer.cpp
+++ b/system/hwc2/HostComposer.cpp
@@ -40,21 +40,6 @@
namespace android {
namespace {
-static bool isMinigbmFromProperty() {
- static constexpr const auto kGrallocProp = "ro.hardware.gralloc";
-
- const auto grallocProp = android::base::GetProperty(kGrallocProp, "");
- DEBUG_LOG("%s: prop value is: %s", __FUNCTION__, grallocProp.c_str());
-
- if (grallocProp == "minigbm") {
- ALOGD("%s: Using minigbm, in minigbm mode.\n", __FUNCTION__);
- return true;
- } else {
- ALOGD("%s: Is not using minigbm, in goldfish mode.\n", __FUNCTION__);
- return false;
- }
-}
-
typedef struct compose_layer {
uint32_t cbHandle;
hwc2_composition_t composeMode;
@@ -139,15 +124,13 @@
} // namespace
-HWC2::Error HostComposer::init(const HotplugCallback& cb) {
- mIsMinigbm = isMinigbmFromProperty();
+HostComposer::HostComposer(DrmPresenter* drmPresenter,
+ bool isMinigbm) :
+ mDrmPresenter(drmPresenter),
+ mIsMinigbm(isMinigbm) {}
- if (mIsMinigbm) {
- if (!mDrmPresenter.init(cb)) {
- ALOGE("%s: failed to initialize DrmPresenter", __FUNCTION__);
- return HWC2::Error::NoResources;
- }
- } else {
+HWC2::Error HostComposer::init() {
+ if (!mIsMinigbm) {
mSyncDeviceFd = goldfish_sync_open();
}
@@ -300,7 +283,7 @@
std::optional<std::vector<uint8_t>> edid;
if (mIsMinigbm) {
- edid = mDrmPresenter.getEdid(displayId);
+ edid = mDrmPresenter->getEdid(displayId);
if (edid) {
display->setEdid(*edid);
}
diff --git a/system/hwc2/HostComposer.h b/system/hwc2/HostComposer.h
index c4c2964..14fc0a7 100644
--- a/system/hwc2/HostComposer.h
+++ b/system/hwc2/HostComposer.h
@@ -29,7 +29,7 @@
class HostComposer : public Composer {
public:
- HostComposer() = default;
+ HostComposer(DrmPresenter* drmPresenter, bool isMinigbm);
HostComposer(const HostComposer&) = delete;
HostComposer& operator=(const HostComposer&) = delete;
@@ -37,7 +37,7 @@
HostComposer(HostComposer&&) = delete;
HostComposer& operator=(HostComposer&&) = delete;
- HWC2::Error init(const HotplugCallback& cb) override;
+ HWC2::Error init() override;
HWC2::Error onDisplayCreate(Display* display) override;
@@ -83,8 +83,7 @@
};
std::unordered_map<hwc2_display_t, HostComposerDisplayInfo> mDisplayInfos;
-
- DrmPresenter mDrmPresenter;
+ DrmPresenter* mDrmPresenter;
};
} // namespace android