diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-09-22 23:01:29 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-09-22 23:01:29 +0000 |
commit | 10495417bbd3317a4812ff0e30b4fc8cb6a18ba1 (patch) | |
tree | 15b42e063b5643d66c26a57c0881346ba7f47d21 | |
parent | 00f3ded2f312ef401e4e5ca680cc4aa9bd5aca26 (diff) | |
parent | 565a5f1903df260c097b4783eac761143fadcbf1 (diff) | |
download | goldfish-opengl-10495417bbd3317a4812ff0e30b4fc8cb6a18ba1.tar.gz |
Snap for 7756953 from 565a5f1903df260c097b4783eac761143fadcbf1 to sc-d2-release
Change-Id: I9721de0de5364b54f5ee1f2807e7158b64ffc9a0
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, ¶m, 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 |