aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-09-22 23:01:29 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-09-22 23:01:29 +0000
commit10495417bbd3317a4812ff0e30b4fc8cb6a18ba1 (patch)
tree15b42e063b5643d66c26a57c0881346ba7f47d21
parent00f3ded2f312ef401e4e5ca680cc4aa9bd5aca26 (diff)
parent565a5f1903df260c097b4783eac761143fadcbf1 (diff)
downloadgoldfish-opengl-10495417bbd3317a4812ff0e30b4fc8cb6a18ba1.tar.gz
Snap for 7756953 from 565a5f1903df260c097b4783eac761143fadcbf1 to sc-d2-release
Change-Id: I9721de0de5364b54f5ee1f2807e7158b64ffc9a0
-rw-r--r--system/OpenglSystemCommon/EmulatorFeatureInfo.h13
-rw-r--r--system/OpenglSystemCommon/HostConnection.cpp16
-rw-r--r--system/OpenglSystemCommon/HostConnection.h5
-rw-r--r--system/hwc2/Android.mk4
-rw-r--r--system/hwc2/Composer.h15
-rw-r--r--system/hwc2/Device.cpp71
-rw-r--r--system/hwc2/Device.h4
-rw-r--r--system/hwc2/Display.cpp86
-rw-r--r--system/hwc2/Display.h35
-rw-r--r--system/hwc2/DisplayFinder.cpp201
-rw-r--r--system/hwc2/DisplayFinder.h46
-rw-r--r--system/hwc2/DrmPresenter.cpp7
-rw-r--r--system/hwc2/DrmPresenter.h2
-rw-r--r--system/hwc2/GuestComposer.cpp162
-rw-r--r--system/hwc2/GuestComposer.h21
-rw-r--r--system/hwc2/HostComposer.cpp454
-rw-r--r--system/hwc2/HostComposer.h19
-rw-r--r--system/hwc2/HostUtils.cpp32
-rw-r--r--system/hwc2/HostUtils.h41
-rw-r--r--system/hwc2/drmTest.cpp2
-rw-r--r--system/hwc2/drmhwcgralloc.h39
-rw-r--r--system/renderControl_enc/renderControl_client_context.cpp3
-rw-r--r--system/renderControl_enc/renderControl_client_context.h3
-rw-r--r--system/renderControl_enc/renderControl_client_proc.h3
-rw-r--r--system/renderControl_enc/renderControl_enc.cpp129
-rw-r--r--system/renderControl_enc/renderControl_entry.cpp21
-rw-r--r--system/renderControl_enc/renderControl_ftable.h3
-rw-r--r--system/renderControl_enc/renderControl_opcodes.h5
28 files changed, 974 insertions, 468 deletions
diff --git a/system/OpenglSystemCommon/EmulatorFeatureInfo.h b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
index a21b2576..8a243c26 100644
--- a/system/OpenglSystemCommon/EmulatorFeatureInfo.h
+++ b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
@@ -129,13 +129,18 @@ static const char kVulkanQueueSubmitWithCommands[] = "ANDROID_EMU_vulkan_queue_s
// Synchronized glBufferData call
static const char kSyncBufferData[] = "ANDROID_EMU_sync_buffer_data";
-
// Batched descriptor set update
static const char kVulkanBatchedDescriptorSetUpdate[] = "ANDROID_EMU_vulkan_batched_descriptor_set_update";
+// Async QSRI
+static const char kVulkanAsyncQsri[] = "ANDROID_EMU_vulkan_async_qsri";
+
// DMA for readback
static const char kReadColorBufferDma[] = "ANDROID_EMU_read_color_buffer_dma";
+// HWC multiple display configs
+static const char kHWCMultiConfigs[] = "ANDROID_EMU_hwc_multi_configs";
+
// Struct describing available emulator features
struct EmulatorFeatureInfo {
@@ -163,7 +168,9 @@ struct EmulatorFeatureInfo {
hasVulkanQueueSubmitWithCommands(false),
hasVulkanBatchedDescriptorSetUpdate(false),
hasSyncBufferData(false),
- hasReadColorBufferDma(false)
+ hasVulkanAsyncQsri(false),
+ hasReadColorBufferDma(false),
+ hasHWCMultiConfigs(false)
{ }
SyncImpl syncImpl;
@@ -189,7 +196,9 @@ struct EmulatorFeatureInfo {
bool hasVulkanQueueSubmitWithCommands;
bool hasVulkanBatchedDescriptorSetUpdate;
bool hasSyncBufferData;
+ bool hasVulkanAsyncQsri;
bool hasReadColorBufferDma;
+ bool hasHWCMultiConfigs;
};
enum HostConnectionType {
diff --git a/system/OpenglSystemCommon/HostConnection.cpp b/system/OpenglSystemCommon/HostConnection.cpp
index 8d15d086..8399f2ad 100644
--- a/system/OpenglSystemCommon/HostConnection.cpp
+++ b/system/OpenglSystemCommon/HostConnection.cpp
@@ -672,7 +672,9 @@ ExtendedRCEncoderContext *HostConnection::rcEncoder()
queryAndSetVulkanQueueSubmitWithCommandsSupport(rcEnc);
queryAndSetVulkanBatchedDescriptorSetUpdateSupport(rcEnc);
queryAndSetSyncBufferData(rcEnc);
+ queryAndSetVulkanAsyncQsri(rcEnc);
queryAndSetReadColorBufferDma(rcEnc);
+ queryAndSetHWCMultiConfigs(rcEnc);
queryVersion(rcEnc);
if (m_processPipe) {
m_processPipe->processPipeInit(m_connectionType, rcEnc);
@@ -972,6 +974,13 @@ void HostConnection::queryAndSetSyncBufferData(ExtendedRCEncoderContext* rcEnc)
}
}
+void HostConnection::queryAndSetVulkanAsyncQsri(ExtendedRCEncoderContext* rcEnc) {
+ std::string glExtensions = queryGLExtensions(rcEnc);
+ if (glExtensions.find(kVulkanAsyncQsri) != std::string::npos) {
+ rcEnc->featureInfo()->hasVulkanAsyncQsri = true;
+ }
+}
+
void HostConnection::queryAndSetReadColorBufferDma(ExtendedRCEncoderContext* rcEnc) {
std::string glExtensions = queryGLExtensions(rcEnc);
if (glExtensions.find(kReadColorBufferDma) != std::string::npos) {
@@ -979,6 +988,13 @@ void HostConnection::queryAndSetReadColorBufferDma(ExtendedRCEncoderContext* rcE
}
}
+void HostConnection::queryAndSetHWCMultiConfigs(ExtendedRCEncoderContext* rcEnc) {
+ std::string glExtensions = queryGLExtensions(rcEnc);
+ if (glExtensions.find(kHWCMultiConfigs) != std::string::npos) {
+ rcEnc->featureInfo()->hasHWCMultiConfigs = true;
+ }
+}
+
GLint HostConnection::queryVersion(ExtendedRCEncoderContext* rcEnc) {
GLint version = m_rcEnc->rcGetRendererVersion(m_rcEnc.get());
return version;
diff --git a/system/OpenglSystemCommon/HostConnection.h b/system/OpenglSystemCommon/HostConnection.h
index 31ca84cf..6bec6acb 100644
--- a/system/OpenglSystemCommon/HostConnection.h
+++ b/system/OpenglSystemCommon/HostConnection.h
@@ -77,6 +77,9 @@ public:
}
bool hasSyncBufferData() const {
return m_featureInfo.hasSyncBufferData; }
+ bool hasHWCMultiConfigs() const {
+ return m_featureInfo.hasHWCMultiConfigs;
+ }
DmaImpl getDmaVersion() const { return m_featureInfo.dmaImpl; }
void bindDmaContext(struct goldfish_dma_context* cxt) { m_dmaCxt = cxt; }
void bindDmaDirectly(void* dmaPtr, uint64_t dmaPhysAddr) {
@@ -244,7 +247,9 @@ private:
void queryAndSetVulkanQueueSubmitWithCommandsSupport(ExtendedRCEncoderContext *rcEnc);
void queryAndSetVulkanBatchedDescriptorSetUpdateSupport(ExtendedRCEncoderContext *rcEnc);
void queryAndSetSyncBufferData(ExtendedRCEncoderContext *rcEnc);
+ void queryAndSetVulkanAsyncQsri(ExtendedRCEncoderContext *rcEnc);
void queryAndSetReadColorBufferDma(ExtendedRCEncoderContext *rcEnc);
+ void queryAndSetHWCMultiConfigs(ExtendedRCEncoderContext* rcEnc);
GLint queryVersion(ExtendedRCEncoderContext* rcEnc);
private:
diff --git a/system/hwc2/Android.mk b/system/hwc2/Android.mk
index 4d207ff9..918251cd 100644
--- a/system/hwc2/Android.mk
+++ b/system/hwc2/Android.mk
@@ -60,11 +60,13 @@ emulator_hwcomposer_relative_path := hw
emulator_hwcomposer2_src_files := \
Device.cpp \
Display.cpp \
+ DisplayFinder.cpp \
Drm.cpp \
DrmPresenter.cpp \
Gralloc.cpp \
GuestComposer.cpp \
HostComposer.cpp \
+ HostUtils.cpp \
Layer.cpp \
include $(CLEAR_VARS)
@@ -76,7 +78,6 @@ LOCAL_SHARED_LIBRARIES += libOpenglSystemCommon lib_renderControl_enc
LOCAL_SHARED_LIBRARIES += libui
LOCAL_SRC_FILES := $(emulator_hwcomposer2_src_files)
LOCAL_C_INCLUDES := $(emulator_hwcomposer_c_includes)
-LOCAL_C_INCLUDES += external/drm_hwcomposer
LOCAL_C_INCLUDES += external/minigbm/cros_gralloc
LOCAL_MODULE_RELATIVE_PATH := $(emulator_hwcomposer_relative_path)
@@ -97,7 +98,6 @@ LOCAL_SHARED_LIBRARIES += libui
LOCAL_SHARED_LIBRARIES += libdrm
LOCAL_C_INCLUDES := $(emulator_hwcomposer_c_includes)
LOCAL_C_INCLUDES += external/libdrm
-LOCAL_C_INCLUDES += external/drm_hwcomposer
LOCAL_C_INCLUDES += external/minigbm/cros_gralloc
LOCAL_MODULE := emulatorDrmTest
LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
diff --git a/system/hwc2/Composer.h b/system/hwc2/Composer.h
index fdbb6b01..b0c3248a 100644
--- a/system/hwc2/Composer.h
+++ b/system/hwc2/Composer.h
@@ -38,19 +38,7 @@ class Composer {
virtual HWC2::Error init(const HotplugCallback& cb) = 0;
- using AddDisplayToDeviceFunction =
- std::function<HWC2::Error(std::unique_ptr<Display>)>;
-
- // Queries Cuttlefish/Goldfish/System configurations and creates displays
- // for the given Device.
- virtual HWC2::Error createDisplays(
- Device* device,
- const AddDisplayToDeviceFunction& addDisplayToDeviceFn) = 0;
-
- virtual HWC2::Error createDisplay(
- Device* device, uint32_t displayId, uint32_t width, uint32_t height,
- uint32_t dpiX, uint32_t dpiY, uint32_t refreshRateHz,
- const AddDisplayToDeviceFunction& addDisplayToDeviceFn) = 0;
+ virtual HWC2::Error onDisplayCreate(Display* display) = 0;
virtual HWC2::Error onDisplayDestroy(Display* display) = 0;
@@ -66,6 +54,7 @@ class Composer {
// to the display.
virtual HWC2::Error presentDisplay(Display* display,
int32_t* outPresentFence) = 0;
+ virtual HWC2::Error onActiveConfigChange(Display* display) = 0;
};
} // namespace android
diff --git a/system/hwc2/Device.cpp b/system/hwc2/Device.cpp
index 24df956e..1f06f439 100644
--- a/system/hwc2/Device.cpp
+++ b/system/hwc2/Device.cpp
@@ -18,6 +18,7 @@
#include <android-base/properties.h>
+#include "DisplayFinder.h"
#include "GuestComposer.h"
#include "HostComposer.h"
@@ -36,7 +37,7 @@ static int CloseHook(hw_device_t* dev) {
return 0;
}
-bool IsCuttlefish() {
+bool ShouldUseGuestComposer() {
return android::base::GetProperty("ro.hardware.vulkan", "") == "pastel";
}
@@ -55,7 +56,7 @@ Device::Device() {
HWC2::Error Device::init() {
DEBUG_LOG("%s", __FUNCTION__);
- if (IsCuttlefish()) {
+ if (ShouldUseGuestComposer()) {
mComposer = std::make_unique<GuestComposer>();
} else {
mComposer = std::make_unique<HostComposer>();
@@ -96,45 +97,59 @@ HWC2::Error Device::createDisplays() {
return HWC2::Error::NoResources;
}
- auto addDisplayLockedFn = [this](std::unique_ptr<Display> display) {
- auto displayId = display->getId();
- DEBUG_LOG("%s: adding display:%" PRIu64, __FUNCTION__, displayId);
- mDisplays.emplace(displayId, std::move(display));
- return HWC2::Error::None;
- };
+ std::vector<DisplayMultiConfigs> displays;
- HWC2::Error error = mComposer->createDisplays(this, addDisplayLockedFn);
+ HWC2::Error error = findDisplays(displays);
if (error != HWC2::Error::None) {
- ALOGE("%s composer failed to create displays", __FUNCTION__);
+ ALOGE("%s failed to find display configs", __FUNCTION__);
return error;
}
+ for (const auto& iter: displays) {
+
+ error = createDisplay(iter.configs, iter.activeConfigId);
+ if (error != HWC2::Error::None) {
+ ALOGE("%s failed to create display from config", __FUNCTION__);
+ return error;
+ }
+ }
+
return HWC2::Error::None;
}
-HWC2::Error Device::createDisplay(uint32_t displayId, uint32_t width,
- uint32_t height, uint32_t dpiX, uint32_t dpiY,
- uint32_t refreshRate) {
+HWC2::Error Device::createDisplay(const std::vector<DisplayConfig>& configs,
+ int activeConfig) {
+ DEBUG_LOG("%s", __FUNCTION__);
+
if (!mComposer) {
ALOGE("%s composer not initialized!", __FUNCTION__);
return HWC2::Error::NoResources;
}
- auto addDisplayLockedFn = [this](std::unique_ptr<Display> display) {
- auto displayId = display->getId();
- DEBUG_LOG("%s: adding display:%" PRIu64, __FUNCTION__, displayId);
- mDisplays.emplace(displayId, std::move(display));
- return HWC2::Error::None;
- };
+ uint32_t displayId = configs[0].id;
+ auto display = std::make_unique<Display>(*this, mComposer.get(),
+ displayId);
+ if (display == nullptr) {
+ ALOGE("%s failed to allocate display", __FUNCTION__);
+ return HWC2::Error::NoResources;
+ }
- HWC2::Error error =
- mComposer->createDisplay(this, displayId, width, height, dpiX, dpiY,
- refreshRate, addDisplayLockedFn);
+ HWC2::Error error = display->init(configs, activeConfig);
if (error != HWC2::Error::None) {
- ALOGE("%s composer failed to create displays", __FUNCTION__);
+ ALOGE("%s failed to initialize display:%" PRIu32, __FUNCTION__, displayId);
return error;
}
+ error = mComposer->onDisplayCreate(display.get());
+ if (error != HWC2::Error::None) {
+ ALOGE("%s failed to register display:%" PRIu32 " with composer",
+ __FUNCTION__, displayId);
+ return error;
+ }
+
+ DEBUG_LOG("%s: adding display:%" PRIu64, __FUNCTION__, displayId);
+ mDisplays.emplace(displayId, std::move(display));
+
return HWC2::Error::None;
}
@@ -524,10 +539,14 @@ bool Device::handleHotplug(bool connected, uint32_t id, uint32_t width,
display->unlock();
}
if (connected) {
- createDisplay(id, width, height, dpiX, dpiY, refreshRate);
+ std::vector<DisplayConfig> config;
+ config.push_back({static_cast<int>(id), static_cast<int>(width),
+ static_cast<int>(height), static_cast<int>(dpiX),
+ static_cast<int>(dpiY), static_cast<int>(refreshRate)});
+ createDisplay(config, 0);
ALOGD("callback hotplugConnect display %" PRIu32 " width %" PRIu32
- " height %" PRIu32 " dpiX %" PRIu32 " dpiY %" PRIu32
- "fps %" PRIu32, id, width, height, dpiX, dpiY, refreshRate);
+ " height %" PRIu32 " dpiX %" PRIu32 " dpiY %" PRIu32 "fps %" PRIu32,
+ id, width, height, dpiX, dpiY, refreshRate);
hotplug(mCallbacks[HWC2::Callback::Hotplug].data, id, hotplugConnect);
};
diff --git a/system/hwc2/Device.h b/system/hwc2/Device.h
index 7c990b9e..b49d1a0f 100644
--- a/system/hwc2/Device.h
+++ b/system/hwc2/Device.h
@@ -53,8 +53,8 @@ class Device : public hwc2_device_t {
HWC2::Error createDisplays();
- HWC2::Error createDisplay(uint32_t displayId, uint32_t width, uint32_t height,
- uint32_t dpiX, uint32_t dpiY, uint32_t refreshRate);
+ HWC2::Error createDisplay(const std::vector<DisplayConfig>& configs,
+ int activeConfig);
Display* getDisplay(hwc2_display_t displayId);
diff --git a/system/hwc2/Display.cpp b/system/hwc2/Display.cpp
index bed6b64f..f95992b4 100644
--- a/system/hwc2/Display.cpp
+++ b/system/hwc2/Display.cpp
@@ -26,6 +26,8 @@
namespace android {
namespace {
+using android::hardware::graphics::common::V1_0::ColorTransform;
+
std::atomic<hwc2_config_t> sNextConfigId{0};
bool IsValidColorMode(android_color_mode_t mode) {
@@ -68,29 +70,34 @@ Display::Display(Device& device, Composer* composer, hwc2_display_t id)
Display::~Display() {}
-HWC2::Error Display::init(uint32_t width, uint32_t height, uint32_t dpiX,
- uint32_t dpiY, uint32_t refreshRateHz,
+HWC2::Error Display::init(const std::vector<DisplayConfig>& configs,
+ int activeConfig,
const std::optional<std::vector<uint8_t>>& edid) {
ALOGD("%s initializing display:%" PRIu64
" width:%d height:%d dpiX:%d dpiY:%d refreshRateHz:%d",
- __FUNCTION__, mId, width, height, dpiX, dpiY, refreshRateHz);
+ __FUNCTION__, mId, configs[activeConfig].width,
+ configs[activeConfig].height,
+ configs[activeConfig].dpiX,
+ configs[activeConfig].dpiY,
+ configs[activeConfig].refreshRateHz);
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
- mVsyncPeriod = 1000 * 1000 * 1000 / refreshRateHz;
+ mVsyncPeriod = 1000 * 1000 * 1000 / configs[activeConfig].refreshRateHz;
mVsyncThread->run("", ANDROID_PRIORITY_URGENT_DISPLAY);
- hwc2_config_t configId = sNextConfigId++;
-
- Config config(configId);
- config.setAttribute(HWC2::Attribute::VsyncPeriod, mVsyncPeriod);
- config.setAttribute(HWC2::Attribute::Width, width);
- config.setAttribute(HWC2::Attribute::Height, height);
- config.setAttribute(HWC2::Attribute::DpiX, dpiX * 1000);
- config.setAttribute(HWC2::Attribute::DpiY, dpiY * 1000);
- mConfigs.emplace(configId, config);
+ for (hwc2_config_t id = 0; id < configs.size(); id++) {
+ Config config(id);
+ config.setAttribute(HWC2::Attribute::VsyncPeriod,
+ 1000 * 1000 * 1000 / configs[id].refreshRateHz);
+ config.setAttribute(HWC2::Attribute::Width, configs[id].width);
+ config.setAttribute(HWC2::Attribute::Height, configs[id].height);
+ config.setAttribute(HWC2::Attribute::DpiX, configs[id].dpiX * 1000);
+ config.setAttribute(HWC2::Attribute::DpiY, configs[id].dpiY * 1000);
+ mConfigs.emplace(id, config);
+ }
+ mActiveConfigId = activeConfig;
- mActiveConfigId = configId;
mActiveColorMode = HAL_COLOR_MODE_NATIVE;
mColorModes.emplace((android_color_mode_t)HAL_COLOR_MODE_NATIVE);
mEdid = edid;
@@ -505,7 +512,14 @@ HWC2::Error Display::setActiveConfig(hwc2_config_t configId) {
return HWC2::Error::BadConfig;
}
- mActiveConfigId = configId;
+ if (mActiveConfigId != configId) {
+ if (mComposer == nullptr) {
+ ALOGE("%s: display:%" PRIu64 " missing composer", __FUNCTION__, mId);
+ return HWC2::Error::NoResources;
+ }
+ mActiveConfigId = configId;
+ return mComposer->onActiveConfigChange(this);
+ }
return HWC2::Error::None;
}
@@ -544,17 +558,38 @@ HWC2::Error Display::setColorMode(int32_t intMode) {
return HWC2::Error::None;
}
-HWC2::Error Display::setColorTransform(const float* /*matrix*/, int32_t hint) {
- DEBUG_LOG("%s: display:%" PRIu64 " setting hint to %d", __FUNCTION__, mId,
- hint);
+HWC2::Error Display::setColorTransform(const float* transformMatrix,
+ int transformTypeRaw) {
+ const auto transformType = static_cast<ColorTransform>(transformTypeRaw);
+ return setColorTransformEnum(transformMatrix, transformType);
+}
+
+HWC2::Error Display::setColorTransformEnum(const float* transformMatrix,
+ ColorTransform transformType) {
+ const auto transformTypeString = toString(transformType);
+ DEBUG_LOG("%s: display:%" PRIu64 " color transform type %s", __FUNCTION__,
+ mId, transformTypeString.c_str());
+
+ if (transformType == ColorTransform::ARBITRARY_MATRIX &&
+ transformMatrix == nullptr) {
+ return HWC2::Error::BadParameter;
+ }
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
- // we force client composition if this is set
- if (hint == 0) {
- mSetColorTransform = false;
+
+ if (transformType == ColorTransform::IDENTITY) {
+ mColorTransform.reset();
} else {
- mSetColorTransform = true;
+ ColorTransformWithMatrix& colorTransform = mColorTransform.emplace();
+ colorTransform.transformType = transformType;
+
+ if (transformType == ColorTransform::ARBITRARY_MATRIX) {
+ auto& colorTransformMatrix = colorTransform.transformMatrixOpt.emplace();
+ std::copy_n(transformMatrix, colorTransformMatrix.size(),
+ colorTransformMatrix.begin());
+ }
}
+
return HWC2::Error::None;
}
@@ -760,6 +795,13 @@ static const uint8_t sEDID2[] = {
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+HWC2::Error Display::setEdid(std::vector<uint8_t> edid) {
+ DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
+
+ mEdid = edid;
+ return HWC2::Error::None;
+}
+
HWC2::Error Display::getDisplayIdentificationData(uint8_t* outPort,
uint32_t* outDataSize,
uint8_t* outData) {
diff --git a/system/hwc2/Display.h b/system/hwc2/Display.h
index 418e26c6..c5385a81 100644
--- a/system/hwc2/Display.h
+++ b/system/hwc2/Display.h
@@ -17,8 +17,10 @@
#ifndef ANDROID_HWC_DISPLAY_H
#define ANDROID_HWC_DISPLAY_H
+#include <android/hardware/graphics/common/1.0/types.h>
#include <utils/Thread.h>
+#include <array>
#include <optional>
#include <set>
#include <thread>
@@ -27,6 +29,7 @@
#include "Common.h"
#include "Composer.h"
+#include "DisplayFinder.h"
#include "FencedBuffer.h"
#include "Layer.h"
@@ -35,6 +38,11 @@ namespace android {
class Composer;
class Device;
+struct ColorTransformWithMatrix {
+ android::hardware::graphics::common::V1_0::ColorTransform transformType;
+ std::optional<std::array<float, 16>> transformMatrixOpt;
+};
+
class Display {
public:
Display(Device& device, Composer* composer, hwc2_display_t id);
@@ -46,14 +54,13 @@ class Display {
Display(Display&& display) = delete;
Display& operator=(Display&& display) = delete;
- HWC2::Error init(uint32_t width, uint32_t height, uint32_t dpiX,
- uint32_t dpiY, uint32_t refreshRateHz,
- const std::optional<std::vector<uint8_t>>& edid = std::nullopt);
+ HWC2::Error init(const std::vector<DisplayConfig>& configs, int activeConfig,
+ const std::optional<std::vector<uint8_t>>& edid = std::nullopt);
- HWC2::Error updateParameters(uint32_t width, uint32_t height, uint32_t dpiX,
- uint32_t dpiY, uint32_t refreshRateHz,
- const std::optional<std::vector<uint8_t>>& edid
- = std::nullopt);
+ HWC2::Error updateParameters(
+ uint32_t width, uint32_t height, uint32_t dpiX, uint32_t dpiY,
+ uint32_t refreshRateHz,
+ const std::optional<std::vector<uint8_t>>& edid = std::nullopt);
hwc2_display_t getId() const { return mId; }
@@ -97,8 +104,15 @@ class Display {
HWC2::Error setClientTarget(buffer_handle_t target, int32_t acquireFence,
int32_t dataspace, hwc_region_t damage);
HWC2::Error setColorMode(int32_t mode);
- HWC2::Error setColorTransform(const float* matrix, int32_t hint);
- bool hasColorTransform() const { return mSetColorTransform; }
+ HWC2::Error setColorTransform(const float* matrix, int transform);
+ HWC2::Error setColorTransformEnum(
+ const float* matrix,
+ android::hardware::graphics::common::V1_0::ColorTransform transform);
+ bool hasColorTransform() const { return mColorTransform.has_value(); }
+ ColorTransformWithMatrix getColorTransform() const {
+ return *mColorTransform;
+ }
+
HWC2::Error setOutputBuffer(buffer_handle_t buffer, int32_t releaseFence);
HWC2::Error setPowerMode(int32_t mode);
HWC2::Error setVsyncEnabled(int32_t enabled);
@@ -107,6 +121,7 @@ class Display {
HWC2::Error updateLayerZ(hwc2_layer_t layerId, uint32_t z);
HWC2::Error getClientTargetSupport(uint32_t width, uint32_t height,
int32_t format, int32_t dataspace);
+ HWC2::Error setEdid(std::vector<uint8_t> edid);
HWC2::Error getDisplayIdentificationData(uint8_t* outPort,
uint32_t* outDataSize,
uint8_t* outData);
@@ -228,7 +243,7 @@ class Display {
std::unordered_map<hwc2_config_t, Config> mConfigs;
std::set<android_color_mode_t> mColorModes;
android_color_mode_t mActiveColorMode;
- bool mSetColorTransform = false;
+ std::optional<ColorTransformWithMatrix> mColorTransform;
std::optional<std::vector<uint8_t>> mEdid;
};
diff --git a/system/hwc2/DisplayFinder.cpp b/system/hwc2/DisplayFinder.cpp
new file mode 100644
index 00000000..90769b5e
--- /dev/null
+++ b/system/hwc2/DisplayFinder.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "DisplayFinder.h"
+
+#include <android-base/parseint.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <device_config_shared.h>
+
+#include "HostUtils.h"
+
+namespace android {
+namespace {
+
+bool IsCuttlefish() {
+ return android::base::GetProperty("ro.product.board", "") == "cutf";
+}
+
+HWC2::Error findCuttlefishDisplays(std::vector<DisplayMultiConfigs>& displays) {
+ DEBUG_LOG("%s", __FUNCTION__);
+
+ // TODO: replace with initializing directly from DRM info.
+ const auto deviceConfig = cuttlefish::GetDeviceConfig();
+
+ int displayId = 0;
+ for (const auto& deviceDisplayConfig : deviceConfig.display_config()) {
+ DisplayMultiConfigs display = {
+ .id = displayId,
+ .activeConfigId = 0,
+ .configs = {{displayId,
+ deviceDisplayConfig.width(),
+ deviceDisplayConfig.height(),
+ deviceDisplayConfig.dpi(),
+ deviceDisplayConfig.dpi(),
+ deviceDisplayConfig.refresh_rate_hz()}},
+ };
+ displays.push_back(display);
+ ++displayId;
+ }
+
+ 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(std::vector<DisplayMultiConfigs>& displays) {
+ DEBUG_LOG("%s", __FUNCTION__);
+
+ DEFINE_AND_VALIDATE_HOST_CONNECTION
+ hostCon->lock();
+ int activeConfigId;
+ const int refreshRateHz = getVsyncHzFromProperty();
+ DisplayMultiConfigs display;
+ display.id = 0;
+ if (rcEnc->hasHWCMultiConfigs()) {
+ int count= rcEnc->rcGetFBDisplayConfigsCount(rcEnc);
+ if (count <= 0) {
+ ALOGE("%s failed to allocate primary display, config count %d", __func__, count);
+ return HWC2::Error::NoResources;
+ }
+ display.activeConfigId = rcEnc->rcGetFBDisplayActiveConfig(rcEnc);
+ for(int configId = 0; configId < count; configId++) {
+ display.configs.push_back({
+ 0,
+ rcEnc->rcGetFBDisplayConfigsParam(
+ rcEnc, configId, FB_WIDTH),
+ rcEnc->rcGetFBDisplayConfigsParam(
+ rcEnc, configId, FB_HEIGHT),
+ rcEnc->rcGetFBDisplayConfigsParam(
+ rcEnc, configId, FB_XDPI),
+ rcEnc->rcGetFBDisplayConfigsParam(
+ rcEnc, configId, FB_YDPI),
+ refreshRateHz,
+ });
+ }
+ } else {
+ display.activeConfigId = 0;
+ display.configs.push_back({
+ 0,
+ rcEnc->rcGetFBParam(rcEnc, FB_WIDTH),
+ rcEnc->rcGetFBParam(rcEnc, FB_HEIGHT),
+ rcEnc->rcGetFBParam(rcEnc, FB_XDPI),
+ rcEnc->rcGetFBParam(rcEnc, FB_YDPI),
+ refreshRateHz});
+ }
+ hostCon->unlock();
+
+ displays.push_back(display);
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error findGoldfishSecondaryDisplays(std::vector<DisplayMultiConfigs>& displays) {
+ DEBUG_LOG("%s", __FUNCTION__);
+
+ static constexpr const char kExternalDisplayProp[] =
+ "hwservicemanager.external.displays";
+
+ const auto propString = android::base::GetProperty(kExternalDisplayProp, "");
+ DEBUG_LOG("%s: prop value is: %s", __FUNCTION__, propString.c_str());
+
+ if (propString.empty()) {
+ return HWC2::Error::None;
+ }
+
+ const std::vector<std::string> propStringParts =
+ android::base::Split(propString, ",");
+ if (propStringParts.size() % 5 != 0) {
+ ALOGE("%s: Invalid syntax for system prop %s which is %s", __FUNCTION__,
+ kExternalDisplayProp, propString.c_str());
+ return HWC2::Error::BadParameter;
+ }
+
+ std::vector<int> propIntParts;
+ for (const std::string& propStringPart : propStringParts) {
+ int propIntPart;
+ if (!android::base::ParseInt(propStringPart, &propIntPart)) {
+ ALOGE("%s: Invalid syntax for system prop %s which is %s", __FUNCTION__,
+ kExternalDisplayProp, propString.c_str());
+ return HWC2::Error::BadParameter;
+ }
+ propIntParts.push_back(propIntPart);
+ }
+
+ int secondaryDisplayId = 1;
+ while (!propIntParts.empty()) {
+ DisplayMultiConfigs display;
+ display.id = secondaryDisplayId;
+ display.activeConfigId = 0;
+ display.configs.push_back(DisplayConfig{
+ .id = secondaryDisplayId,
+ .width = propIntParts[1],
+ .height = propIntParts[2],
+ .dpiX = propIntParts[3],
+ .dpiY = propIntParts[3],
+ .refreshRateHz = 160,
+ });
+ displays.push_back(display);
+
+ ++secondaryDisplayId;
+
+ propIntParts.erase(propIntParts.begin(), propIntParts.begin() + 5);
+ }
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error findGoldfishDisplays(std::vector<DisplayMultiConfigs>& displays) {
+ HWC2::Error error = findGoldfishPrimaryDisplay(displays);
+ if (error != HWC2::Error::None) {
+ ALOGE("%s failed to find Goldfish primary display", __FUNCTION__);
+ return error;
+ }
+
+ error = findGoldfishSecondaryDisplays(displays);
+ if (error != HWC2::Error::None) {
+ ALOGE("%s failed to find Goldfish secondary displays", __FUNCTION__);
+ }
+
+ return error;
+}
+
+} // namespace
+
+HWC2::Error findDisplays(std::vector<DisplayMultiConfigs>& displays) {
+ if (IsCuttlefish()) {
+ return findCuttlefishDisplays(displays);
+ } else {
+ return findGoldfishDisplays(displays);
+ }
+}
+
+} // namespace android
diff --git a/system/hwc2/DisplayFinder.h b/system/hwc2/DisplayFinder.h
new file mode 100644
index 00000000..44a09a60
--- /dev/null
+++ b/system/hwc2/DisplayFinder.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HWC_DISPLAYFINDER_H
+#define ANDROID_HWC_DISPLAYFINDER_H
+
+#include <vector>
+
+#include "Common.h"
+
+namespace android {
+
+struct DisplayConfig {
+ int id;
+ int width;
+ int height;
+ int dpiX;
+ int dpiY;
+ int refreshRateHz;
+};
+
+struct DisplayMultiConfigs {
+ int id;
+ int activeConfigId;
+ // Modes that this display can be configured to use.
+ std::vector<DisplayConfig> configs;
+};
+
+HWC2::Error findDisplays(std::vector<DisplayMultiConfigs>& displays);
+
+} // namespace android
+
+#endif
diff --git a/system/hwc2/DrmPresenter.cpp b/system/hwc2/DrmPresenter.cpp
index 4d63c58c..1c6350f5 100644
--- a/system/hwc2/DrmPresenter.cpp
+++ b/system/hwc2/DrmPresenter.cpp
@@ -223,7 +223,8 @@ bool DrmPresenter::initDrmElementsLocked() {
if (!strcmp(connectorProp->name, "CRTC_ID")) {
connector.mCrtcPropertyId = connectorProp->prop_id;
} else if (!strcmp(connectorProp->name, "EDID")) {
- connector.mEdidBlobId = connectorProps->prop_values[connectorPropIndex];
+ connector.mEdidBlobId =
+ connectorProps->prop_values[connectorPropIndex];
}
drmModeFreeProperty(connectorProp);
}
@@ -501,8 +502,8 @@ std::optional<std::vector<uint8_t>> DrmPresenter::getEdid(uint32_t id) {
ALOGW("%s: EDID not supported", __func__);
return std::nullopt;
}
- drmModePropertyBlobPtr blob = drmModeGetPropertyBlob(mFd.get(),
- mConnectors[id].mEdidBlobId);
+ drmModePropertyBlobPtr blob =
+ drmModeGetPropertyBlob(mFd.get(), mConnectors[id].mEdidBlobId);
if (!blob) {
ALOGE("%s: fail to read EDID from DRM", __func__);
return std::nullopt;
diff --git a/system/hwc2/DrmPresenter.h b/system/hwc2/DrmPresenter.h
index 7f9edb2c..d65ce9d1 100644
--- a/system/hwc2/DrmPresenter.h
+++ b/system/hwc2/DrmPresenter.h
@@ -18,7 +18,6 @@
#define ANDROID_HWC_DRMPRESENTER_H
#include <android-base/unique_fd.h>
-#include <include/drmhwcgralloc.h>
#include <utils/Thread.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
@@ -27,6 +26,7 @@
#include <memory>
#include <vector>
+#include "drmhwcgralloc.h"
#include "Common.h"
#include "android/base/synchronization/AndroidLock.h"
diff --git a/system/hwc2/GuestComposer.cpp b/system/hwc2/GuestComposer.cpp
index 1518d4fe..e635639a 100644
--- a/system/hwc2/GuestComposer.cpp
+++ b/system/hwc2/GuestComposer.cpp
@@ -19,6 +19,7 @@
#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/strings.h>
+#include <android/hardware/graphics/common/1.0/types.h>
#include <device_config_shared.h>
#include <drm_fourcc.h>
#include <libyuv.h>
@@ -34,6 +35,8 @@
namespace android {
namespace {
+using android::hardware::graphics::common::V1_0::ColorTransform;
+
uint64_t AlignToPower2(uint64_t val, uint8_t align_log) {
uint64_t align = 1ULL << align_log;
return ((val + (align - 1)) / align) * align;
@@ -391,56 +394,32 @@ HWC2::Error GuestComposer::init(const HotplugCallback& cb) {
return HWC2::Error::None;
}
-HWC2::Error GuestComposer::createDisplays(
- Device* device, const AddDisplayToDeviceFunction& addDisplayToDeviceFn) {
- DEBUG_LOG("%s", __FUNCTION__);
-
- HWC2::Error error = HWC2::Error::None;
-
- std::vector<DisplayConfig> displayConfigs;
+HWC2::Error GuestComposer::onDisplayCreate(Display* display) {
+ hwc2_display_t displayId = display->getId();
+ hwc2_config_t displayConfigId;
+ int32_t displayWidth;
+ int32_t displayHeight;
- error = getDisplayConfigsFromDeviceConfig(&displayConfigs);
+ HWC2::Error error = display->getActiveConfig(&displayConfigId);
if (error != HWC2::Error::None) {
- ALOGE("%s failed to get display configs from device config", __FUNCTION__);
+ ALOGE("%s: display:%" PRIu64 " has no active config", __FUNCTION__,
+ displayId);
return error;
}
- error = getDisplayConfigsFromSystemProp(&displayConfigs);
+ error = display->getDisplayAttributeEnum(
+ displayConfigId, HWC2::Attribute::Width, &displayWidth);
if (error != HWC2::Error::None) {
- ALOGE("%s failed to get display configs from system prop", __FUNCTION__);
+ ALOGE("%s: display:%" PRIu64 " failed to get width", __FUNCTION__,
+ displayId);
return error;
}
- uint32_t id = 0;
- for (const auto& displayConfig : displayConfigs) {
- error = createDisplay(device, id, displayConfig.width, displayConfig.height,
- displayConfig.dpiX, displayConfig.dpiY,
- displayConfig.refreshRateHz, addDisplayToDeviceFn);
- if (error != HWC2::Error::None) {
- ALOGE("%s: failed to create display %d", __FUNCTION__, id);
- return error;
- }
-
- ++id;
- }
-
- return HWC2::Error::None;
-}
-
-HWC2::Error GuestComposer::createDisplay(
- Device* device, uint32_t id, uint32_t width, uint32_t height, uint32_t dpiX,
- uint32_t dpiY, uint32_t refreshRateHz,
- const AddDisplayToDeviceFunction& addDisplayToDeviceFn) {
- auto display = std::make_unique<Display>(*device, this, id);
- if (display == nullptr) {
- ALOGE("%s failed to allocate display", __FUNCTION__);
- return HWC2::Error::NoResources;
- }
- auto displayId = display->getId();
-
- HWC2::Error error = display->init(width, height, dpiX, dpiY, refreshRateHz);
+ error = display->getDisplayAttributeEnum(
+ displayConfigId, HWC2::Attribute::Height, &displayHeight);
if (error != HWC2::Error::None) {
- ALOGE("%s failed to initialize display:%" PRIu64, __FUNCTION__, displayId);
+ ALOGE("%s: display:%" PRIu64 " failed to get height", __FUNCTION__,
+ displayId);
return error;
}
@@ -455,8 +434,8 @@ HWC2::Error GuestComposer::createDisplay(
buffer_handle_t bufferHandle;
auto status = GraphicBufferAllocator::get().allocate(
- width, //
- height, //
+ displayWidth, //
+ displayHeight, //
PIXEL_FORMAT_RGBA_8888, //
/*layerCount=*/1, //
GraphicBuffer::USAGE_HW_COMPOSER | GraphicBuffer::USAGE_SW_READ_OFTEN |
@@ -492,12 +471,6 @@ HWC2::Error GuestComposer::createDisplay(
}
}
- error = addDisplayToDeviceFn(std::move(display));
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to add display:%" PRIu64, __FUNCTION__, displayId);
- return error;
- }
-
return HWC2::Error::None;
}
@@ -631,10 +604,6 @@ HWC2::Error GuestComposer::validateDisplay(
}
}
- if (display->hasColorTransform()) {
- fallbackToClientComposition = true;
- }
-
if (fallbackToClientComposition) {
for (Layer* layer : layers) {
const auto layerId = layer->getId();
@@ -836,6 +805,23 @@ HWC2::Error GuestComposer::presentDisplay(Display* display,
}
}
+ if (display->hasColorTransform()) {
+ const ColorTransformWithMatrix colorTransform =
+ display->getColorTransform();
+
+ HWC2::Error error =
+ applyColorTransformToRGBA(colorTransform, //
+ compositionResultBufferData, //
+ compositionResultBufferWidth, //
+ compositionResultBufferHeight, //
+ compositionResultBufferStride);
+ if (error != HWC2::Error::None) {
+ ALOGE("%s: display:%" PRIu64 " failed to apply color transform",
+ __FUNCTION__, displayId);
+ return error;
+ }
+ }
+
DEBUG_LOG("%s display:%" PRIu64 " flushing drm buffer", __FUNCTION__,
displayId);
@@ -1067,6 +1053,78 @@ HWC2::Error GuestComposer::composeLayerInto(
return HWC2::Error::None;
}
+namespace {
+
+static constexpr const std::array<float, 16> kInvertColorMatrix = {
+ // clang-format off
+ -1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f, 0.0f,
+ 0.0f, -1.0f, -1.0f, 0.0f,
+ 1.0f, 1.0f, 1.0f, 1.0f,
+ // clang-format on
+};
+
+// Returns a color matrix that can be used with libyuv by converting values
+// in -1 to 1 into -64 to 64 and transposing.
+std::array<std::int8_t, 16> ToLibyuvColorMatrix(
+ const std::array<float, 16>& in) {
+ std::array<std::int8_t, 16> out;
+
+ for (int r = 0; r < 4; r++) {
+ for (int c = 0; c < 4; c++) {
+ int indexIn = (4 * r) + c;
+ int indexOut = (4 * c) + r;
+
+ out[indexOut] = std::max(
+ -128, std::min(127, static_cast<int>(in[indexIn] * 64.0f + 0.5f)));
+ }
+ }
+
+ return out;
+}
+
+} // namespace
+
+HWC2::Error GuestComposer::applyColorTransformToRGBA(
+ const ColorTransformWithMatrix& transform, //
+ std::uint8_t* buffer, //
+ std::uint32_t bufferWidth, //
+ std::uint32_t bufferHeight, //
+ std::uint32_t bufferStrideBytes) {
+ if (transform.transformType == ColorTransform::ARBITRARY_MATRIX) {
+ if (!transform.transformMatrixOpt.has_value()) {
+ ALOGE("%s: color transform matrix missing", __FUNCTION__);
+ return HWC2::Error::BadParameter;
+ }
+ const auto& transformMatrix = *transform.transformMatrixOpt;
+ const auto transformMatrixLibyuv = ToLibyuvColorMatrix(transformMatrix);
+ libyuv::ARGBColorMatrix(buffer, bufferStrideBytes, // in buffer params
+ buffer, bufferStrideBytes, // out buffer params
+ transformMatrixLibyuv.data(), //
+ bufferWidth, //
+ bufferHeight);
+ } else if (transform.transformType == ColorTransform::VALUE_INVERSE) {
+ const auto transformMatrixLibyuv = ToLibyuvColorMatrix(kInvertColorMatrix);
+ libyuv::ARGBColorMatrix(buffer, bufferStrideBytes, // in buffer params
+ buffer, bufferStrideBytes, // out buffer params
+ transformMatrixLibyuv.data(), //
+ bufferWidth, //
+ bufferHeight);
+ } else if (transform.transformType == ColorTransform::GRAYSCALE) {
+ libyuv::ARGBGrayTo(buffer, bufferStrideBytes, // in buffer params
+ buffer, bufferStrideBytes, // out buffer params
+ bufferWidth, //
+ bufferHeight);
+ } else {
+ const auto transformTypeString = toString(transform.transformType);
+ ALOGE("%s: unhandled color transform type %s", __FUNCTION__,
+ transformTypeString.c_str());
+ return HWC2::Error::BadParameter;
+ }
+
+ return HWC2::Error::None;
+}
+
uint8_t* GuestComposer::getRotatingScratchBuffer(std::size_t neededSize,
std::uint32_t order) {
static constexpr const int kNumScratchBufferPieces = 2;
diff --git a/system/hwc2/GuestComposer.h b/system/hwc2/GuestComposer.h
index 930cbee6..db6bf3e7 100644
--- a/system/hwc2/GuestComposer.h
+++ b/system/hwc2/GuestComposer.h
@@ -19,6 +19,7 @@
#include "Common.h"
#include "Composer.h"
+#include "Display.h"
#include "DrmPresenter.h"
#include "Gralloc.h"
#include "Layer.h"
@@ -37,14 +38,7 @@ class GuestComposer : public Composer {
HWC2::Error init(const HotplugCallback& cb) override;
- HWC2::Error createDisplays(
- Device* device,
- const AddDisplayToDeviceFunction& addDisplayToDeviceFn) override;
-
- HWC2::Error createDisplay(
- Device* device, uint32_t displayId, uint32_t width, uint32_t height,
- uint32_t dpiX, uint32_t dpiY, uint32_t refreshRateHz,
- const AddDisplayToDeviceFunction& addDisplayToDeviceFn) override;
+ HWC2::Error onDisplayCreate(Display*) override;
HWC2::Error onDisplayDestroy(Display*) override;
@@ -63,6 +57,10 @@ class GuestComposer : public Composer {
HWC2::Error presentDisplay(Display* display,
int32_t* outPresentFence) override;
+ HWC2::Error onActiveConfigChange(Display* /*display*/) override {
+ return HWC2::Error::None;
+ };
+
private:
struct DisplayConfig {
int width;
@@ -109,6 +107,13 @@ class GuestComposer : public Composer {
std::uint32_t order);
uint8_t* getSpecialScratchBuffer(std::size_t neededSize);
+ HWC2::Error applyColorTransformToRGBA(
+ const ColorTransformWithMatrix& colotTransform, //
+ std::uint8_t* buffer, //
+ std::uint32_t bufferWidth, //
+ std::uint32_t bufferHeight, //
+ std::uint32_t bufferStrideBytes);
+
std::vector<uint8_t> mScratchBuffer;
std::vector<uint8_t> mSpecialScratchBuffer;
};
diff --git a/system/hwc2/HostComposer.cpp b/system/hwc2/HostComposer.cpp
index c55eccd9..9501bb69 100644
--- a/system/hwc2/HostComposer.cpp
+++ b/system/hwc2/HostComposer.cpp
@@ -31,26 +31,11 @@
#include "../egl/goldfish_sync.h"
#include "Device.h"
#include "Display.h"
+#include "HostUtils.h"
namespace android {
namespace {
-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);
-}
-
static bool isMinigbmFromProperty() {
static constexpr const auto kGrallocProp = "ro.hardware.gralloc";
@@ -66,25 +51,19 @@ static bool isMinigbmFromProperty() {
}
}
-#define DEFINE_AND_VALIDATE_HOST_CONNECTION \
- HostConnection* hostCon = createOrGetHostConnection(); \
- if (!hostCon) { \
- ALOGE("%s: Failed to get host connection\n", __FUNCTION__); \
- return HWC2::Error::NoResources; \
- } \
- ExtendedRCEncoderContext* rcEnc = hostCon->rcEncoder(); \
- if (!rcEnc) { \
- ALOGE("%s: Failed to get renderControl encoder context\n", __FUNCTION__); \
- return HWC2::Error::NoResources; \
- }
+static bool useAngleFromProperty() {
+ static constexpr const auto kEglProp = "ro.hardware.egl";
-static std::unique_ptr<HostConnection> sHostCon;
+ const auto eglProp = android::base::GetProperty(kEglProp, "");
+ DEBUG_LOG("%s: prop value is: %s", __FUNCTION__, eglProp.c_str());
-static HostConnection* createOrGetHostConnection() {
- if (!sHostCon) {
- sHostCon = HostConnection::createUnique();
+ if (eglProp == "angle") {
+ ALOGD("%s: Using ANGLE.\n", __FUNCTION__);
+ return true;
+ } else {
+ ALOGD("%s: Not using ANGLE.\n", __FUNCTION__);
+ return false;
}
- return sHostCon.get();
}
typedef struct compose_layer {
@@ -173,6 +152,8 @@ void FreeDisplayColorBuffer(const native_handle_t* h) {
HWC2::Error HostComposer::init(const HotplugCallback& cb) {
mIsMinigbm = isMinigbmFromProperty();
+ mUseAngle = useAngleFromProperty();
+
if (mIsMinigbm) {
if (!mDrmPresenter.init(cb)) {
ALOGE("%s: failed to initialize DrmPresenter", __FUNCTION__);
@@ -185,253 +166,77 @@ HWC2::Error HostComposer::init(const HotplugCallback& cb) {
return HWC2::Error::None;
}
-HWC2::Error HostComposer::createDisplays(
- Device* device, const AddDisplayToDeviceFunction& addDisplayToDeviceFn) {
+HWC2::Error HostComposer::createHostComposerDisplayInfo(
+ Display* display, uint32_t hostDisplayId) {
HWC2::Error error = HWC2::Error::None;
- error = createPrimaryDisplay(device, addDisplayToDeviceFn);
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to create primary display", __FUNCTION__);
- return error;
- }
+ hwc2_display_t displayId = display->getId();
+ hwc2_config_t displayConfigId;
+ int32_t displayWidth;
+ int32_t displayHeight;
- error = createSecondaryDisplays(device, addDisplayToDeviceFn);
+ error = display->getActiveConfig(&displayConfigId);
if (error != HWC2::Error::None) {
- ALOGE("%s failed to create secondary displays", __FUNCTION__);
+ ALOGE("%s: display:%" PRIu64 " has no active config", __FUNCTION__,
+ displayId);
return error;
}
- return HWC2::Error::None;
-}
-
-HWC2::Error HostComposer::createPrimaryDisplay(
- Device* device, const AddDisplayToDeviceFunction& addDisplayToDeviceFn) {
- HWC2::Error error = HWC2::Error::None;
-
- DEFINE_AND_VALIDATE_HOST_CONNECTION
- hostCon->lock();
- int width = rcEnc->rcGetFBParam(rcEnc, FB_WIDTH);
- int height = rcEnc->rcGetFBParam(rcEnc, FB_HEIGHT);
- int dpiX = rcEnc->rcGetFBParam(rcEnc, FB_XDPI);
- int dpiY = rcEnc->rcGetFBParam(rcEnc, FB_YDPI);
- hostCon->unlock();
-
- int refreshRateHz = getVsyncHzFromProperty();
-
- auto display = std::make_unique<Display>(*device, this, 0);
- if (display == nullptr) {
- ALOGE("%s failed to allocate display", __FUNCTION__);
- return HWC2::Error::NoResources;
- }
-
- auto displayId = display->getId();
-
- error = display->init(width, height, dpiX, dpiY, refreshRateHz);
+ error = display->getDisplayAttributeEnum(
+ displayConfigId, HWC2::Attribute::Width, &displayWidth);
if (error != HWC2::Error::None) {
- ALOGE("%s failed to initialize display:%" PRIu64, __FUNCTION__, displayId);
+ ALOGE("%s: display:%" PRIu64 " failed to get width", __FUNCTION__,
+ displayId);
return error;
}
- error = createHostComposerDisplayInfo(display.get(), /*hostDisplayId=*/0);
+ error = display->getDisplayAttributeEnum(
+ displayConfigId, HWC2::Attribute::Height, &displayHeight);
if (error != HWC2::Error::None) {
- ALOGE("%s failed to initialize host info for display:%" PRIu64,
- __FUNCTION__, displayId);
+ ALOGE("%s: display:%" PRIu64 " failed to get height", __FUNCTION__,
+ displayId);
return error;
}
- error = addDisplayToDeviceFn(std::move(display));
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to add display:%" PRIu64, __FUNCTION__, displayId);
- return error;
- }
+ HostComposerDisplayInfo& displayInfo = mDisplayInfos[displayId];
- return HWC2::Error::None;
-}
+ displayInfo.hostDisplayId = hostDisplayId;
-HWC2::Error HostComposer::createDisplay(
- Device* device, uint32_t displayId, uint32_t width, uint32_t height,
- uint32_t dpiX, uint32_t dpiY, uint32_t refreshRateHz,
- const AddDisplayToDeviceFunction& addDisplayToDeviceFn) {
- HWC2::Error error;
- Display* display = device->getDisplay(displayId);
- if (display) {
- ALOGD("%s display %d already existed, then update", __func__, displayId);
+ if (displayInfo.compositionResultBuffer) {
+ FreeDisplayColorBuffer(displayInfo.compositionResultBuffer);
}
-
- DEFINE_AND_VALIDATE_HOST_CONNECTION
- hostCon->lock();
- if (rcEnc->rcCreateDisplayById(rcEnc, displayId)) {
- ALOGE("%s host failed to create display %" PRIu32, __func__, displayId);
- hostCon->unlock();
- return HWC2::Error::NoResources;
- }
- if (rcEnc->rcSetDisplayPoseDpi(rcEnc, displayId, -1, -1, width, height, dpiX/1000)) {
- ALOGE("%s host failed to set display %" PRIu32, __func__, displayId);
- hostCon->unlock();
+ displayInfo.compositionResultBuffer =
+ AllocateDisplayColorBuffer(displayWidth, displayHeight);
+ if (displayInfo.compositionResultBuffer == nullptr) {
+ ALOGE("%s: display:%" PRIu64 " failed to create target buffer",
+ __FUNCTION__, displayId);
return HWC2::Error::NoResources;
}
- hostCon->unlock();
- std::optional<std::vector<uint8_t>> edid;
if (mIsMinigbm) {
- edid = mDrmPresenter.getEdid(displayId);
- }
- if (!display) {
- auto newDisplay = std::make_unique<Display>(*device, this, displayId);
- if (newDisplay == nullptr) {
- ALOGE("%s failed to allocate display", __FUNCTION__);
- return HWC2::Error::NoResources;
- }
-
-
- error = newDisplay->init(width, height, dpiX, dpiY, refreshRateHz, edid);
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to initialize display:%" PRIu32, __FUNCTION__,
- displayId);
- return error;
- }
-
- error =
- createHostComposerDisplayInfo(newDisplay.get(), displayId);
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to initialize host info for display:%" PRIu32,
- __FUNCTION__, displayId);
- return error;
- }
-
- error = addDisplayToDeviceFn(std::move(newDisplay));
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to add display:%" PRIu32, __FUNCTION__, displayId);
- return error;
- }
- } else {
- display->lock();
- // update display parameters
- error = display->updateParameters(width, height, dpiX, dpiY,
- refreshRateHz, edid);
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to update display:%" PRIu32, __FUNCTION__, displayId);
- display->unlock();
- return error;
- }
-
- error = createHostComposerDisplayInfo(display, displayId);
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to initialize host info for display:%" PRIu32,
- __FUNCTION__, displayId);
- display->unlock();
- return error;
- }
- display->unlock();
- }
-
- return HWC2::Error::None;
-}
-
-HWC2::Error HostComposer::createSecondaryDisplays(
- Device* device, const AddDisplayToDeviceFunction& addDisplayToDeviceFn) {
- HWC2::Error error = HWC2::Error::None;
-
- static constexpr const char kExternalDisplayProp[] =
- "hwservicemanager.external.displays";
-
- const auto propString = android::base::GetProperty(kExternalDisplayProp, "");
- DEBUG_LOG("%s: prop value is: %s", __FUNCTION__, propString.c_str());
-
- if (propString.empty()) {
- return HWC2::Error::None;
- }
-
- const std::vector<std::string> propStringParts =
- android::base::Split(propString, ",");
- if (propStringParts.size() % 5 != 0) {
- ALOGE("%s: Invalid syntax for system prop %s which is %s", __FUNCTION__,
- kExternalDisplayProp, propString.c_str());
- return HWC2::Error::BadParameter;
- }
-
- std::vector<int> propIntParts;
- for (const std::string& propStringPart : propStringParts) {
- uint64_t propUintPart;
- if (!android::base::ParseUint(propStringPart, &propUintPart)) {
- ALOGE("%s: Invalid syntax for system prop %s which is %s", __FUNCTION__,
- kExternalDisplayProp, propString.c_str());
- return HWC2::Error::BadParameter;
- }
- propIntParts.push_back(static_cast<int>(propUintPart));
- }
-
- static constexpr const uint32_t kHostDisplayIdStart = 6;
-
- uint32_t secondaryDisplayIndex = 1;
- while (!propIntParts.empty()) {
- int width = propIntParts[1];
- int height = propIntParts[2];
- int dpiX = propIntParts[3];
- int dpiY = propIntParts[3];
- int refreshRateHz = 160;
-
- propIntParts.erase(propIntParts.begin(), propIntParts.begin() + 5);
-
- uint32_t expectedHostDisplayId =
- kHostDisplayIdStart + secondaryDisplayIndex - 1;
- uint32_t actualHostDisplayId = 0;
-
- DEFINE_AND_VALIDATE_HOST_CONNECTION
- hostCon->lock();
- rcEnc->rcDestroyDisplay(rcEnc, expectedHostDisplayId);
- rcEnc->rcCreateDisplay(rcEnc, &actualHostDisplayId);
- rcEnc->rcSetDisplayPose(rcEnc, actualHostDisplayId, -1, -1, width, height);
- hostCon->unlock();
-
- if (actualHostDisplayId != expectedHostDisplayId) {
- ALOGE(
- "Something wrong with host displayId allocation, expected %d "
- "but received %d",
- expectedHostDisplayId, actualHostDisplayId);
- }
-
- auto display =
- std::make_unique<Display>(*device, this, secondaryDisplayIndex++);
- if (display == nullptr) {
- ALOGE("%s failed to allocate display", __FUNCTION__);
- return HWC2::Error::NoResources;
- }
-
- auto displayId = display->getId();
+ displayInfo.compositionResultDrmBuffer.reset(
+ new DrmBuffer(displayInfo.compositionResultBuffer, mDrmPresenter));
- error = display->init(width, height, dpiX, dpiY, refreshRateHz);
+ uint32_t vsyncPeriod = 1000 * 1000 * 1000 / mDrmPresenter.refreshRate();
+ error = display->setVsyncPeriod(vsyncPeriod);
if (error != HWC2::Error::None) {
- ALOGE("%s failed to initialize display:%" PRIu64, __FUNCTION__,
+ ALOGE("%s: display:%" PRIu64 " failed to set vsync height", __FUNCTION__,
displayId);
return error;
}
-
- error = createHostComposerDisplayInfo(display.get(), actualHostDisplayId);
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to initialize host info for display:%" PRIu64,
- __FUNCTION__, displayId);
- return error;
- }
-
- error = addDisplayToDeviceFn(std::move(display));
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to add display:%" PRIu64, __FUNCTION__, displayId);
- return error;
- }
}
return HWC2::Error::None;
}
-HWC2::Error HostComposer::createHostComposerDisplayInfo(
- Display* display, uint32_t hostDisplayId) {
+HWC2::Error HostComposer::onDisplayCreate(Display* display) {
HWC2::Error error = HWC2::Error::None;
hwc2_display_t displayId = display->getId();
hwc2_config_t displayConfigId;
int32_t displayWidth;
int32_t displayHeight;
+ int32_t displayDpiX;
error = display->getActiveConfig(&displayConfigId);
if (error != HWC2::Error::None) {
@@ -456,33 +261,68 @@ HWC2::Error HostComposer::createHostComposerDisplayInfo(
return error;
}
- auto it = mDisplayInfos.find(displayId);
- if (it != mDisplayInfos.end()) {
- ALOGE("%s: display:%" PRIu64 " already created?", __FUNCTION__, displayId);
+ error = display->getDisplayAttributeEnum(displayConfigId,
+ HWC2::Attribute::DpiX, &displayDpiX);
+ if (error != HWC2::Error::None) {
+ ALOGE("%s: display:%" PRIu64 " failed to get height", __FUNCTION__,
+ displayId);
+ return error;
}
- HostComposerDisplayInfo& displayInfo = mDisplayInfos[displayId];
+ uint32_t hostDisplayId = 0;
- displayInfo.hostDisplayId = hostDisplayId;
+ DEFINE_AND_VALIDATE_HOST_CONNECTION
+ if (displayId == 0) {
+ // Primary display:
+ hostCon->lock();
+ if (rcEnc->rcCreateDisplayById(rcEnc, displayId)) {
+ ALOGE("%s host failed to create display %" PRIu64, __func__, displayId);
+ hostCon->unlock();
+ return HWC2::Error::NoResources;
+ }
+ if (rcEnc->rcSetDisplayPoseDpi(rcEnc, displayId, -1, -1, displayWidth,
+ displayHeight, displayDpiX / 1000)) {
+ ALOGE("%s host failed to set display %" PRIu64, __func__, displayId);
+ hostCon->unlock();
+ return HWC2::Error::NoResources;
+ }
+ hostCon->unlock();
+ } else {
+ // Secondary display:
+ static constexpr const uint32_t kHostDisplayIdStart = 6;
- displayInfo.compositionResultBuffer =
- AllocateDisplayColorBuffer(displayWidth, displayHeight);
- if (displayInfo.compositionResultBuffer == nullptr) {
- ALOGE("%s: display:%" PRIu64 " failed to create target buffer",
+ uint32_t expectedHostDisplayId = kHostDisplayIdStart + displayId - 1;
+ uint32_t actualHostDisplayId = 0;
+
+ hostCon->lock();
+ rcEnc->rcDestroyDisplay(rcEnc, expectedHostDisplayId);
+ rcEnc->rcCreateDisplay(rcEnc, &actualHostDisplayId);
+ rcEnc->rcSetDisplayPose(rcEnc, actualHostDisplayId, -1, -1, displayWidth,
+ displayHeight);
+ hostCon->unlock();
+
+ if (actualHostDisplayId != expectedHostDisplayId) {
+ ALOGE(
+ "Something wrong with host displayId allocation, expected %d "
+ "but received %d",
+ expectedHostDisplayId, actualHostDisplayId);
+ }
+
+ hostDisplayId = actualHostDisplayId;
+ }
+
+ error = createHostComposerDisplayInfo(display, hostDisplayId);
+ if (error != HWC2::Error::None) {
+ ALOGE("%s failed to initialize host info for display:%" PRIu64,
__FUNCTION__, displayId);
- return HWC2::Error::NoResources;
+ return error;
}
+ std::optional<std::vector<uint8_t>> edid;
if (mIsMinigbm) {
- displayInfo.compositionResultDrmBuffer.reset(
- new DrmBuffer(displayInfo.compositionResultBuffer, mDrmPresenter));
-
- uint32_t vsyncPeriod = 1000 * 1000 * 1000 / mDrmPresenter.refreshRate();
- error = display->setVsyncPeriod(vsyncPeriod);
- if (error != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " failed to set vsync height", __FUNCTION__,
- displayId);
- return error;
+ edid = mDrmPresenter.getEdid(displayId);
+ if (edid) {
+ display->setEdid(*edid);
}
}
@@ -740,53 +580,31 @@ HWC2::Error HostComposer::presentDisplay(Display* display,
p2->numLayers = numLayer;
}
+ void *buffer;
+ uint32_t bufferSize;
+ if (hostCompositionV1) {
+ buffer = (void*)p;
+ bufferSize = sizeof(ComposeDevice) + numLayer * sizeof(ComposeLayer);
+ } else {
+ bufferSize = sizeof(ComposeDevice_v2) + numLayer * sizeof(ComposeLayer);
+ buffer = (void*)p2;
+ }
+
+ int retire_fd = -1;
hostCon->lock();
if (rcEnc->hasAsyncFrameCommands()) {
if (mIsMinigbm) {
- if (hostCompositionV1) {
- rcEnc->rcComposeAsyncWithoutPost(
- rcEnc, sizeof(ComposeDevice) + numLayer * sizeof(ComposeLayer),
- (void*)p);
- } else {
- rcEnc->rcComposeAsyncWithoutPost(
- rcEnc, sizeof(ComposeDevice_v2) + numLayer * sizeof(ComposeLayer),
- (void*)p2);
- }
+ rcEnc->rcComposeAsyncWithoutPost(rcEnc, bufferSize, buffer);
} else {
- if (hostCompositionV1) {
- rcEnc->rcComposeAsync(
- rcEnc, sizeof(ComposeDevice) + numLayer * sizeof(ComposeLayer),
- (void*)p);
- } else {
- rcEnc->rcComposeAsync(
- rcEnc, sizeof(ComposeDevice_v2) + numLayer * sizeof(ComposeLayer),
- (void*)p2);
- }
+ rcEnc->rcComposeAsync(rcEnc, bufferSize, buffer);
}
} else {
if (mIsMinigbm) {
- if (hostCompositionV1) {
- rcEnc->rcComposeWithoutPost(
- rcEnc, sizeof(ComposeDevice) + numLayer * sizeof(ComposeLayer),
- (void*)p);
- } else {
- rcEnc->rcComposeWithoutPost(
- rcEnc, sizeof(ComposeDevice_v2) + numLayer * sizeof(ComposeLayer),
- (void*)p2);
- }
+ rcEnc->rcComposeWithoutPost(rcEnc, bufferSize, buffer);
} else {
- if (hostCompositionV1) {
- rcEnc->rcCompose(
- rcEnc, sizeof(ComposeDevice) + numLayer * sizeof(ComposeLayer),
- (void*)p);
- } else {
- rcEnc->rcCompose(
- rcEnc, sizeof(ComposeDevice_v2) + numLayer * sizeof(ComposeLayer),
- (void*)p2);
- }
+ rcEnc->rcCompose(rcEnc, bufferSize, buffer);
}
}
-
hostCon->unlock();
// Send a retire fence and use it as the release fence for all layers,
@@ -795,13 +613,18 @@ HWC2::Error HostComposer::presentDisplay(Display* display,
EGL_NO_NATIVE_FENCE_FD_ANDROID};
uint64_t sync_handle, thread_handle;
- int retire_fd;
- hostCon->lock();
- rcEnc->rcCreateSyncKHR(rcEnc, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs,
- 2 * sizeof(EGLint), true /* destroy when signaled */,
- &sync_handle, &thread_handle);
- hostCon->unlock();
+ // We don't use rc command to sync if we are using ANGLE on the guest with
+ // virtio-gpu.
+ bool useRcCommandToSync = !(mUseAngle && mIsMinigbm);
+
+ if (useRcCommandToSync) {
+ hostCon->lock();
+ rcEnc->rcCreateSyncKHR(
+ rcEnc, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs, 2 * sizeof(EGLint),
+ true /* destroy when signaled */, &sync_handle, &thread_handle);
+ hostCon->unlock();
+ }
if (mIsMinigbm) {
displayInfo.compositionResultDrmBuffer->flushToDisplay(display->getId(),
@@ -817,13 +640,15 @@ HWC2::Error HostComposer::presentDisplay(Display* display,
*outRetireFence = dup(retire_fd);
close(retire_fd);
- hostCon->lock();
- if (rcEnc->hasAsyncFrameCommands()) {
- rcEnc->rcDestroySyncKHRAsync(rcEnc, sync_handle);
- } else {
- rcEnc->rcDestroySyncKHR(rcEnc, sync_handle);
+ if (useRcCommandToSync) {
+ hostCon->lock();
+ if (rcEnc->hasAsyncFrameCommands()) {
+ rcEnc->rcDestroySyncKHRAsync(rcEnc, sync_handle);
+ } else {
+ rcEnc->rcDestroySyncKHR(rcEnc, sync_handle);
+ }
+ hostCon->unlock();
}
- hostCon->unlock();
} else {
// we set all layers Composition::Client, so do nothing.
@@ -855,4 +680,15 @@ void HostComposer::post(HostConnection* hostCon,
hostCon->unlock();
}
+HWC2::Error HostComposer::onActiveConfigChange(Display* display) {
+ DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, display->getId());
+ HWC2::Error error = createHostComposerDisplayInfo(display, display->getId());
+ if (error != HWC2::Error::None) {
+ ALOGE("%s failed to update host info for display:%" PRIu64,
+ __FUNCTION__, display->getId());
+ return error;
+ }
+ return HWC2::Error::None;
+}
+
} // namespace android
diff --git a/system/hwc2/HostComposer.h b/system/hwc2/HostComposer.h
index fe4a49f8..f722ffc6 100644
--- a/system/hwc2/HostComposer.h
+++ b/system/hwc2/HostComposer.h
@@ -36,14 +36,7 @@ class HostComposer : public Composer {
HWC2::Error init(const HotplugCallback& cb) override;
- HWC2::Error createDisplays(
- Device* device,
- const AddDisplayToDeviceFunction& addDisplayToDeviceFn) override;
-
- HWC2::Error createDisplay(
- Device* device, uint32_t displayId, uint32_t width, uint32_t height,
- uint32_t dpiX, uint32_t dpiY, uint32_t refreshRateHz,
- const AddDisplayToDeviceFunction& addDisplayToDeviceFn) override;
+ HWC2::Error onDisplayCreate(Display* display) override;
HWC2::Error onDisplayDestroy(Display* display) override;
@@ -60,13 +53,9 @@ class HostComposer : public Composer {
HWC2::Error presentDisplay(Display* display,
int32_t* outPresentFence) override;
- private:
- HWC2::Error createPrimaryDisplay(
- Device* device, const AddDisplayToDeviceFunction& addDisplayToDeviceFn);
-
- HWC2::Error createSecondaryDisplays(
- Device* device, const AddDisplayToDeviceFunction& addDisplayToDeviceFn);
+ HWC2::Error onActiveConfigChange(Display* display) override;
+ private:
HWC2::Error createHostComposerDisplayInfo(Display* display,
uint32_t hostDisplayId);
@@ -75,6 +64,8 @@ class HostComposer : public Composer {
bool mIsMinigbm = false;
+ bool mUseAngle = false;
+
int mSyncDeviceFd = -1;
struct HostComposerDisplayInfo {
diff --git a/system/hwc2/HostUtils.cpp b/system/hwc2/HostUtils.cpp
new file mode 100644
index 00000000..11bb6bab
--- /dev/null
+++ b/system/hwc2/HostUtils.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "HostUtils.h"
+
+#include <memory>
+
+namespace android {
+
+HostConnection* createOrGetHostConnection() {
+ static std::unique_ptr<HostConnection> sHostCon;
+
+ if (!sHostCon) {
+ sHostCon = HostConnection::createUnique();
+ }
+ return sHostCon.get();
+}
+
+} // namespace android \ No newline at end of file
diff --git a/system/hwc2/HostUtils.h b/system/hwc2/HostUtils.h
new file mode 100644
index 00000000..65505487
--- /dev/null
+++ b/system/hwc2/HostUtils.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HWC_HOSTUTILS_H
+#define ANDROID_HWC_HOSTUTILS_H
+
+#include "Common.h"
+#include "HostConnection.h"
+
+namespace android {
+
+HostConnection* createOrGetHostConnection();
+
+#define DEFINE_AND_VALIDATE_HOST_CONNECTION \
+ HostConnection* hostCon = createOrGetHostConnection(); \
+ if (!hostCon) { \
+ ALOGE("%s: Failed to get host connection\n", __FUNCTION__); \
+ return HWC2::Error::NoResources; \
+ } \
+ ExtendedRCEncoderContext* rcEnc = hostCon->rcEncoder(); \
+ if (!rcEnc) { \
+ ALOGE("%s: Failed to get renderControl encoder context\n", __FUNCTION__); \
+ return HWC2::Error::NoResources; \
+ }
+
+} // namespace android
+
+#endif \ No newline at end of file
diff --git a/system/hwc2/drmTest.cpp b/system/hwc2/drmTest.cpp
index 86267daf..254772c5 100644
--- a/system/hwc2/drmTest.cpp
+++ b/system/hwc2/drmTest.cpp
@@ -107,7 +107,7 @@ static HostConnection *createOrGetHostConnection() {
return; \
}
-#include "include/drmhwcgralloc.h"
+#include "drmhwcgralloc.h"
void convertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) {
cros_gralloc_handle *gr_handle = (cros_gralloc_handle *)handle;
if (!gr_handle) return;
diff --git a/system/hwc2/drmhwcgralloc.h b/system/hwc2/drmhwcgralloc.h
new file mode 100644
index 00000000..05b2cf01
--- /dev/null
+++ b/system/hwc2/drmhwcgralloc.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_DRMHWCGRALLOC_H_
+#define ANDROID_DRMHWCGRALLOC_H_
+
+#include <stdint.h>
+
+#define HWC_DRM_BO_MAX_PLANES 4
+typedef struct hwc_drm_bo {
+ uint32_t width;
+ uint32_t height;
+ uint32_t format; /* DRM_FORMAT_* from drm_fourcc.h */
+ uint32_t hal_format; /* HAL_PIXEL_FORMAT_* */
+ uint32_t usage;
+ uint32_t pitches[HWC_DRM_BO_MAX_PLANES];
+ uint32_t offsets[HWC_DRM_BO_MAX_PLANES];
+ uint32_t prime_fds[HWC_DRM_BO_MAX_PLANES];
+ uint32_t gem_handles[HWC_DRM_BO_MAX_PLANES];
+ uint64_t modifiers[HWC_DRM_BO_MAX_PLANES];
+ uint32_t fb_id;
+ int acquire_fence_fd;
+ void *priv;
+} hwc_drm_bo_t;
+
+#endif // ANDROID_DRMHWCGRALLOC_H_
diff --git a/system/renderControl_enc/renderControl_client_context.cpp b/system/renderControl_enc/renderControl_client_context.cpp
index eb5c921d..27dd37e2 100644
--- a/system/renderControl_enc/renderControl_client_context.cpp
+++ b/system/renderControl_enc/renderControl_client_context.cpp
@@ -75,6 +75,9 @@ int renderControl_client_context_t::initDispatchByName(void *(*getProc)(const ch
rcCreateDisplayById = (rcCreateDisplayById_client_proc_t) getProc("rcCreateDisplayById", userData);
rcSetDisplayPoseDpi = (rcSetDisplayPoseDpi_client_proc_t) getProc("rcSetDisplayPoseDpi", userData);
rcReadColorBufferDMA = (rcReadColorBufferDMA_client_proc_t) getProc("rcReadColorBufferDMA", userData);
+ rcGetFBDisplayConfigsCount = (rcGetFBDisplayConfigsCount_client_proc_t) getProc("rcGetFBDisplayConfigsCount", userData);
+ rcGetFBDisplayConfigsParam = (rcGetFBDisplayConfigsParam_client_proc_t) getProc("rcGetFBDisplayConfigsParam", userData);
+ rcGetFBDisplayActiveConfig = (rcGetFBDisplayActiveConfig_client_proc_t) getProc("rcGetFBDisplayActiveConfig", userData);
return 0;
}
diff --git a/system/renderControl_enc/renderControl_client_context.h b/system/renderControl_enc/renderControl_client_context.h
index 395e4bbf..862a70da 100644
--- a/system/renderControl_enc/renderControl_client_context.h
+++ b/system/renderControl_enc/renderControl_client_context.h
@@ -75,6 +75,9 @@ struct renderControl_client_context_t {
rcCreateDisplayById_client_proc_t rcCreateDisplayById;
rcSetDisplayPoseDpi_client_proc_t rcSetDisplayPoseDpi;
rcReadColorBufferDMA_client_proc_t rcReadColorBufferDMA;
+ rcGetFBDisplayConfigsCount_client_proc_t rcGetFBDisplayConfigsCount;
+ rcGetFBDisplayConfigsParam_client_proc_t rcGetFBDisplayConfigsParam;
+ rcGetFBDisplayActiveConfig_client_proc_t rcGetFBDisplayActiveConfig;
virtual ~renderControl_client_context_t() {}
typedef renderControl_client_context_t *CONTEXT_ACCESSOR_TYPE(void);
diff --git a/system/renderControl_enc/renderControl_client_proc.h b/system/renderControl_enc/renderControl_client_proc.h
index 2e52898c..2c281271 100644
--- a/system/renderControl_enc/renderControl_client_proc.h
+++ b/system/renderControl_enc/renderControl_client_proc.h
@@ -77,6 +77,9 @@ typedef void (renderControl_APIENTRY *rcComposeAsyncWithoutPost_client_proc_t) (
typedef int (renderControl_APIENTRY *rcCreateDisplayById_client_proc_t) (void * ctx, uint32_t);
typedef int (renderControl_APIENTRY *rcSetDisplayPoseDpi_client_proc_t) (void * ctx, uint32_t, GLint, GLint, uint32_t, uint32_t, uint32_t);
typedef int (renderControl_APIENTRY *rcReadColorBufferDMA_client_proc_t) (void * ctx, uint32_t, GLint, GLint, GLint, GLint, GLenum, GLenum, void*, uint32_t);
+typedef int (renderControl_APIENTRY *rcGetFBDisplayConfigsCount_client_proc_t) (void * ctx);
+typedef int (renderControl_APIENTRY *rcGetFBDisplayConfigsParam_client_proc_t) (void * ctx, int, EGLint);
+typedef int (renderControl_APIENTRY *rcGetFBDisplayActiveConfig_client_proc_t) (void * ctx);
#endif
diff --git a/system/renderControl_enc/renderControl_enc.cpp b/system/renderControl_enc/renderControl_enc.cpp
index 5efed5f2..7fdcab92 100644
--- a/system/renderControl_enc/renderControl_enc.cpp
+++ b/system/renderControl_enc/renderControl_enc.cpp
@@ -2523,8 +2523,8 @@ int rcReadColorBufferDMA_enc(void *self , uint32_t colorbuffer, GLint x, GLint y
if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
- // stream->readback(pixels, __size_pixels);
- // if (useChecksum) checksumCalculator->addBuffer(pixels, __size_pixels);
+ // Skip readback for var pixels as it's DMA
+ // Skip checksum for var pixels as it's DMA
int retval;
stream->readback(&retval, 4);
@@ -2542,6 +2542,128 @@ int rcReadColorBufferDMA_enc(void *self , uint32_t colorbuffer, GLint x, GLint y
return retval;
}
+int rcGetFBDisplayConfigsCount_enc(void *self )
+{
+ AEMU_SCOPED_TRACE("rcGetFBDisplayConfigsCount encode");
+
+ renderControl_encoder_context_t *ctx = (renderControl_encoder_context_t *)self;
+ IOStream *stream = ctx->m_stream;
+ ChecksumCalculator *checksumCalculator = ctx->m_checksumCalculator;
+ bool useChecksum = checksumCalculator->getVersion() > 0;
+
+ unsigned char *ptr;
+ unsigned char *buf;
+ const size_t sizeWithoutChecksum = 8;
+ const size_t checksumSize = checksumCalculator->checksumByteSize();
+ const size_t totalSize = sizeWithoutChecksum + checksumSize;
+ buf = stream->alloc(totalSize);
+ ptr = buf;
+ int tmp = OP_rcGetFBDisplayConfigsCount;memcpy(ptr, &tmp, 4); ptr += 4;
+ memcpy(ptr, &totalSize, 4); ptr += 4;
+
+
+ if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+ if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+
+ int retval;
+ stream->readback(&retval, 4);
+ if (useChecksum) checksumCalculator->addBuffer(&retval, 4);
+ if (useChecksum) {
+ unsigned char *checksumBufPtr = NULL;
+ unsigned char checksumBuf[ChecksumCalculator::kMaxChecksumSize];
+ if (checksumSize > 0) checksumBufPtr = &checksumBuf[0];
+ stream->readback(checksumBufPtr, checksumSize);
+ if (!checksumCalculator->validate(checksumBufPtr, checksumSize)) {
+ ALOGE("rcGetFBDisplayConfigsCount: GL communication error, please report this issue to b.android.com.\n");
+ abort();
+ }
+ }
+ return retval;
+}
+
+int rcGetFBDisplayConfigsParam_enc(void *self , int configId, EGLint param)
+{
+ AEMU_SCOPED_TRACE("rcGetFBDisplayConfigsParam encode");
+
+ renderControl_encoder_context_t *ctx = (renderControl_encoder_context_t *)self;
+ IOStream *stream = ctx->m_stream;
+ ChecksumCalculator *checksumCalculator = ctx->m_checksumCalculator;
+ bool useChecksum = checksumCalculator->getVersion() > 0;
+
+ unsigned char *ptr;
+ unsigned char *buf;
+ const size_t sizeWithoutChecksum = 8 + 4 + 4;
+ const size_t checksumSize = checksumCalculator->checksumByteSize();
+ const size_t totalSize = sizeWithoutChecksum + checksumSize;
+ buf = stream->alloc(totalSize);
+ ptr = buf;
+ int tmp = OP_rcGetFBDisplayConfigsParam;memcpy(ptr, &tmp, 4); ptr += 4;
+ memcpy(ptr, &totalSize, 4); ptr += 4;
+
+ memcpy(ptr, &configId, 4); ptr += 4;
+ memcpy(ptr, &param, 4); ptr += 4;
+
+ if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+ if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+
+ int retval;
+ stream->readback(&retval, 4);
+ if (useChecksum) checksumCalculator->addBuffer(&retval, 4);
+ if (useChecksum) {
+ unsigned char *checksumBufPtr = NULL;
+ unsigned char checksumBuf[ChecksumCalculator::kMaxChecksumSize];
+ if (checksumSize > 0) checksumBufPtr = &checksumBuf[0];
+ stream->readback(checksumBufPtr, checksumSize);
+ if (!checksumCalculator->validate(checksumBufPtr, checksumSize)) {
+ ALOGE("rcGetFBDisplayConfigsParam: GL communication error, please report this issue to b.android.com.\n");
+ abort();
+ }
+ }
+ return retval;
+}
+
+int rcGetFBDisplayActiveConfig_enc(void *self )
+{
+ AEMU_SCOPED_TRACE("rcGetFBDisplayActiveConfig encode");
+
+ renderControl_encoder_context_t *ctx = (renderControl_encoder_context_t *)self;
+ IOStream *stream = ctx->m_stream;
+ ChecksumCalculator *checksumCalculator = ctx->m_checksumCalculator;
+ bool useChecksum = checksumCalculator->getVersion() > 0;
+
+ unsigned char *ptr;
+ unsigned char *buf;
+ const size_t sizeWithoutChecksum = 8;
+ const size_t checksumSize = checksumCalculator->checksumByteSize();
+ const size_t totalSize = sizeWithoutChecksum + checksumSize;
+ buf = stream->alloc(totalSize);
+ ptr = buf;
+ int tmp = OP_rcGetFBDisplayActiveConfig;memcpy(ptr, &tmp, 4); ptr += 4;
+ memcpy(ptr, &totalSize, 4); ptr += 4;
+
+
+ if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+ if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+
+ int retval;
+ stream->readback(&retval, 4);
+ if (useChecksum) checksumCalculator->addBuffer(&retval, 4);
+ if (useChecksum) {
+ unsigned char *checksumBufPtr = NULL;
+ unsigned char checksumBuf[ChecksumCalculator::kMaxChecksumSize];
+ if (checksumSize > 0) checksumBufPtr = &checksumBuf[0];
+ stream->readback(checksumBufPtr, checksumSize);
+ if (!checksumCalculator->validate(checksumBufPtr, checksumSize)) {
+ ALOGE("rcGetFBDisplayActiveConfig: GL communication error, please report this issue to b.android.com.\n");
+ abort();
+ }
+ }
+ return retval;
+}
+
} // namespace
renderControl_encoder_context_t::renderControl_encoder_context_t(IOStream *stream, ChecksumCalculator *checksumCalculator)
@@ -2614,5 +2736,8 @@ renderControl_encoder_context_t::renderControl_encoder_context_t(IOStream *strea
this->rcCreateDisplayById = &rcCreateDisplayById_enc;
this->rcSetDisplayPoseDpi = &rcSetDisplayPoseDpi_enc;
this->rcReadColorBufferDMA = &rcReadColorBufferDMA_enc;
+ this->rcGetFBDisplayConfigsCount = &rcGetFBDisplayConfigsCount_enc;
+ this->rcGetFBDisplayConfigsParam = &rcGetFBDisplayConfigsParam_enc;
+ this->rcGetFBDisplayActiveConfig = &rcGetFBDisplayActiveConfig_enc;
}
diff --git a/system/renderControl_enc/renderControl_entry.cpp b/system/renderControl_enc/renderControl_entry.cpp
index 5b2bedd6..e756322d 100644
--- a/system/renderControl_enc/renderControl_entry.cpp
+++ b/system/renderControl_enc/renderControl_entry.cpp
@@ -70,6 +70,9 @@ extern "C" {
int rcCreateDisplayById(uint32_t displayId);
int rcSetDisplayPoseDpi(uint32_t displayId, GLint x, GLint y, uint32_t w, uint32_t h, uint32_t dpi);
int rcReadColorBufferDMA(uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void* pixels, uint32_t pixels_size);
+ int rcGetFBDisplayConfigsCount();
+ int rcGetFBDisplayConfigsParam(int configId, EGLint param);
+ int rcGetFBDisplayActiveConfig();
};
#ifndef GET_CONTEXT
@@ -468,3 +471,21 @@ int rcReadColorBufferDMA(uint32_t colorbuffer, GLint x, GLint y, GLint width, GL
return ctx->rcReadColorBufferDMA(ctx, colorbuffer, x, y, width, height, format, type, pixels, pixels_size);
}
+int rcGetFBDisplayConfigsCount()
+{
+ GET_CONTEXT;
+ return ctx->rcGetFBDisplayConfigsCount(ctx);
+}
+
+int rcGetFBDisplayConfigsParam(int configId, EGLint param)
+{
+ GET_CONTEXT;
+ return ctx->rcGetFBDisplayConfigsParam(ctx, configId, param);
+}
+
+int rcGetFBDisplayActiveConfig()
+{
+ GET_CONTEXT;
+ return ctx->rcGetFBDisplayActiveConfig(ctx);
+}
+
diff --git a/system/renderControl_enc/renderControl_ftable.h b/system/renderControl_enc/renderControl_ftable.h
index 577cbaeb..9a0f9e9a 100644
--- a/system/renderControl_enc/renderControl_ftable.h
+++ b/system/renderControl_enc/renderControl_ftable.h
@@ -73,6 +73,9 @@ static const struct _renderControl_funcs_by_name {
{"rcCreateDisplayById", (void*)rcCreateDisplayById},
{"rcSetDisplayPoseDpi", (void*)rcSetDisplayPoseDpi},
{"rcReadColorBufferDMA", (void*)rcReadColorBufferDMA},
+ {"rcGetFBDisplayConfigsCount", (void*)rcGetFBDisplayConfigsCount},
+ {"rcGetFBDisplayConfigsParam", (void*)rcGetFBDisplayConfigsParam},
+ {"rcGetFBDisplayActiveConfig", (void*)rcGetFBDisplayActiveConfig},
};
static const int renderControl_num_funcs = sizeof(renderControl_funcs_by_name) / sizeof(struct _renderControl_funcs_by_name);
diff --git a/system/renderControl_enc/renderControl_opcodes.h b/system/renderControl_enc/renderControl_opcodes.h
index 00249d6a..cf4ff828 100644
--- a/system/renderControl_enc/renderControl_opcodes.h
+++ b/system/renderControl_enc/renderControl_opcodes.h
@@ -68,7 +68,10 @@
#define OP_rcCreateDisplayById 10062
#define OP_rcSetDisplayPoseDpi 10063
#define OP_rcReadColorBufferDMA 10064
-#define OP_last 10065
+#define OP_rcGetFBDisplayConfigsCount 10065
+#define OP_rcGetFBDisplayConfigsParam 10066
+#define OP_rcGetFBDisplayActiveConfig 10067
+#define OP_last 10068
#endif