aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHuihong Luo <huisinro@google.com>2019-09-04 13:11:42 -0700
committerandroid-build-merger <android-build-merger@google.com>2019-09-04 13:11:42 -0700
commite849bc0d0c6dfc0ad46b7d537e5b21ed3c547fc8 (patch)
tree93b7f1d807339e02dd0c12610b22d15331765175
parentccff49b278ea5b36ec512937582c60178a743b54 (diff)
parentf97ddfce1c649ab7fc5f76c8c774e5c240b11853 (diff)
downloadgoldfish-opengl-temp_140451723.tar.gz
Merge "Add external physical display emulation"temp_140451723
am: f97ddfce1c Change-Id: Ie9e72b0498dcc2341d26286e9763efb68a13d3b0
-rw-r--r--system/hwc2/EmuHWC2.cpp108
-rw-r--r--system/hwc2/EmuHWC2.h4
2 files changed, 112 insertions, 0 deletions
diff --git a/system/hwc2/EmuHWC2.cpp b/system/hwc2/EmuHWC2.cpp
index 31e07895..3bda1a1b 100644
--- a/system/hwc2/EmuHWC2.cpp
+++ b/system/hwc2/EmuHWC2.cpp
@@ -21,6 +21,7 @@
#define LOG_TAG "EmuHWC2"
#include <errno.h>
+#include <cutils/properties.h>
#include <log/log.h>
#include <sync/sync.h>
@@ -350,6 +351,13 @@ Error EmuHWC2::registerCallback(Callback descriptor,
lock.unlock();
auto hotplug = reinterpret_cast<HWC2_PFN_VSYNC>(pointer);
hotplug(callbackData, 0, static_cast<int32_t>(Connection::Connected));
+
+ int ret = populateSecondaryDisplays();
+ if (ret < 0) {
+ ALOGE("Failed to populate secondary displays");
+ } else if (ret == 0) {
+ hotplug(callbackData, 1, static_cast<int32_t>(Connection::Connected));
+ }
}
return Error::None;
@@ -1138,6 +1146,42 @@ int EmuHWC2::Display::populatePrimaryConfigs() {
return 0;
}
+HWC2::Error EmuHWC2::Display::populateSecondaryConfigs(uint32_t width, uint32_t height,
+ uint32_t dpi) {
+ ALOGVV("%s DisplayId %u, width %u, height %u, dpi %u",
+ __FUNCTION__, (uint32_t)mId, width, height, dpi);
+ std::unique_lock<std::mutex> lock(mStateMutex);
+
+ mGralloc.reset(new GrallocModule());
+ auto newConfig = std::make_shared<Config>(*this);
+ // vsync is 60 hz;
+ newConfig->setAttribute(Attribute::VsyncPeriod, mVsyncPeriod);
+ newConfig->setAttribute(Attribute::Width, width);
+ newConfig->setAttribute(Attribute::Height, height);
+ newConfig->setAttribute(Attribute::DpiX, dpi*1000);
+ newConfig->setAttribute(Attribute::DpiY, dpi*1000);
+
+ newConfig->setId(static_cast<hwc2_config_t>(mConfigs.size()));
+ ALOGV("Found new secondary config %d: %s", (uint32_t)newConfig->getId(),
+ newConfig->toString().c_str());
+ mConfigs.emplace_back(std::move(newConfig));
+
+ // we need to reset these values after populatePrimaryConfigs()
+ mActiveConfig = mConfigs[0];
+ mActiveColorMode = HAL_COLOR_MODE_NATIVE;
+ mColorModes.emplace((android_color_mode_t)HAL_COLOR_MODE_NATIVE);
+
+ uint32_t displayId = 0;
+ DEFINE_AND_VALIDATE_HOST_CONNECTION
+
+ hostCon->lock();
+ rcEnc->rcCreateDisplay(rcEnc, &displayId);
+ rcEnc->rcSetDisplayPose(rcEnc, displayId, -1, -1, width, height);
+ hostCon->unlock();
+
+ return HWC2::Error::None;
+}
+
// Config functions
@@ -1397,6 +1441,70 @@ int EmuHWC2::populatePrimary() {
return ret;
}
+// Note "hwservicemanager." is used to avoid selinux issue
+#define EXTERANL_DISPLAY_PROP "hwservicemanager.external.displays"
+
+// return 0 for successful, 1 if no external displays are specified
+// return < 0 if failed
+int EmuHWC2::populateSecondaryDisplays() {
+ // this guest property, hwservicemanager.external.displays,
+ // specifies multi-display info, with comma (,) as separator
+ // each display has the following info:
+ // physicalId,width,height,dpi,flags
+ // serveral displays can be provided, e.g., following has 2 displays:
+ // setprop hwservicemanager.external.displays 1,1200,800,120,0,2,1200,800,120,0
+ std::vector<uint64_t> values;
+ char displaysValue[PROPERTY_VALUE_MAX] = "";
+ property_get(EXTERANL_DISPLAY_PROP, displaysValue, "");
+ bool isValid = displaysValue[0] != '\0';
+ if (isValid) {
+ char *p = displaysValue;
+ while (*p) {
+ if (!isdigit(*p) && *p != ',' && *p != ' ') {
+ isValid = false;
+ break;
+ }
+ p ++;
+ }
+ if (!isValid) {
+ ALOGE("Invalid syntax for the value of system prop: %s", EXTERANL_DISPLAY_PROP);
+ }
+ }
+ if (!isValid) {
+ // no external displays are specified
+ return 1;
+ }
+ // parse all int values to a vector
+ std::istringstream stream(displaysValue);
+ for (uint64_t id; stream >> id;) {
+ values.push_back(id);
+ if (stream.peek() == ',')
+ stream.ignore();
+ }
+ // each display has 5 values
+ if ((values.size() % 5) != 0) {
+ ALOGE("%s: invalid value for system property: %s", __FUNCTION__, EXTERANL_DISPLAY_PROP);
+ return -1;
+ }
+ while (!values.empty()) {
+ uint64_t physicalId = values[0];
+ uint32_t width = values[1];
+ uint32_t height = values[2];
+ uint32_t dpi = values[3];
+ uint32_t flags = values[4];
+ values.erase(values.begin(), values.begin() + 5);
+
+ Error ret = Error::None;
+ auto display = std::make_shared<Display>(*this, HWC2::DisplayType::Physical);
+ ret = display->populateSecondaryConfigs(width, height, dpi);
+ if (ret != Error::None) {
+ return -2;
+ }
+ mDisplays.emplace(display->getId(), std::move(display));
+ }
+ return 0;
+}
+
EmuHWC2::Display* EmuHWC2::getDisplay(hwc2_display_t id) {
auto display = mDisplays.find(id);
if (display == mDisplays.end()) {
diff --git a/system/hwc2/EmuHWC2.h b/system/hwc2/EmuHWC2.h
index 899d7344..1c0dd51e 100644
--- a/system/hwc2/EmuHWC2.h
+++ b/system/hwc2/EmuHWC2.h
@@ -27,6 +27,7 @@
#include <atomic>
#include <map>
#include <mutex>
+#include <sstream>
#include <vector>
#include <unordered_set>
#include <unordered_map>
@@ -42,6 +43,7 @@ class EmuHWC2 : public hwc2_device_t {
public:
EmuHWC2();
int populatePrimary();
+ int populateSecondaryDisplays();
private:
static inline EmuHWC2* getHWC2(hwc2_device_t* device) {
@@ -258,6 +260,8 @@ private:
// Read configs from PRIMARY Display
int populatePrimaryConfigs();
+ HWC2::Error populateSecondaryConfigs(uint32_t width, uint32_t height,
+ uint32_t dpi);
private:
class Config {