author | baocheng sun <baocheng.sun@amlogic.com> | 2019-12-24 05:58:07 (GMT) |
---|---|---|
committer | sky zhou <sky.zhou@amlogic.com> | 2020-05-21 11:08:47 (GMT) |
commit | 734918da9d1ec127eedc10a54ce408752443236c (patch) | |
tree | c100aaf76a7a940a9ddd21a9a6eeb7e0667b9788 | |
parent | be100acbec50b07d02bfbae495ea2cb4f4ca278e (diff) | |
download | hwcomposer-734918da9d1ec127eedc10a54ce408752443236c.zip hwcomposer-734918da9d1ec127eedc10a54ce408752443236c.tar.gz hwcomposer-734918da9d1ec127eedc10a54ce408752443236c.tar.bz2 |
hwc: add vendor composer service [1/3]
PD#SWPL-18099
Problem:
When playing a 4k video and press back in YouTube, SurfaceView will not
be destroyed. And in composer service process, there is a composerLayer.
CompserLayer has a ComposerHandleCache which will hold the graphic
buffer handles cached in it and lead to ion orphaned memory.
Solution:
Add vendor composer service.
Verify:
Verify on newton
Change-Id: Ia7cac783941354ada82639990eadadac38603dc8
Signed-off-by: baocheng sun <baocheng.sun@amlogic.com>
18 files changed, 3824 insertions, 0 deletions
diff --git a/service/2.1/utils/hal/Android.bp b/service/2.1/utils/hal/Android.bp new file mode 100644 index 0000000..7a501fc --- a/dev/null +++ b/service/2.1/utils/hal/Android.bp @@ -0,0 +1,39 @@ +// +// Copyright (C) 2018 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. + +cc_library_headers { + name: "android.hardware.graphics.composer@2.1-hal", + defaults: ["hidl_defaults"], + vendor_available: true, + shared_libs: [ + "android.hardware.graphics.composer@2.1", + "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@3.0", + "libhardware", // TODO remove hwcomposer2.h dependency + ], + export_shared_lib_headers: [ + "android.hardware.graphics.composer@2.1", + "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@3.0", + "libhardware", + ], + header_libs: [ + "android.hardware.graphics.composer@2.1-command-buffer", + ], + export_header_lib_headers: [ + "android.hardware.graphics.composer@2.1-command-buffer", + ], + export_include_dirs: ["include"], +} diff --git a/service/2.1/utils/hal/include/composer-hal/2.1/Composer.h b/service/2.1/utils/hal/include/composer-hal/2.1/Composer.h new file mode 100644 index 0000000..90d9b98 --- a/dev/null +++ b/service/2.1/utils/hal/include/composer-hal/2.1/Composer.h @@ -0,0 +1,156 @@ +/* + * Copyright 2016 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. + */ + +#pragma once + +#ifndef LOG_TAG +#warning "Composer.h included without LOG_TAG" +#endif + +#include <array> +#include <chrono> +#include <condition_variable> +#include <memory> +#include <mutex> +#include <vector> + +#include <android/hardware/graphics/composer/2.1/IComposer.h> +#include <android/hardware/graphics/composer/2.1/IComposerClient.h> +#include <composer-hal/2.1/ComposerClient.h> +#include <composer-hal/2.1/ComposerHal.h> + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_1 { +namespace hal { + +namespace detail { + +// ComposerImpl implements V2_*::IComposer on top of V2_*::ComposerHal +template <typename Interface, typename Hal> +class ComposerImpl : public Interface { + public: + static std::unique_ptr<ComposerImpl> create(std::unique_ptr<Hal> hal) { + return std::make_unique<ComposerImpl>(std::move(hal)); + } + + ComposerImpl(std::unique_ptr<Hal> hal) : mHal(std::move(hal)) {} + + // IComposer 2.1 interface + + Return<void> getCapabilities(IComposer::getCapabilities_cb hidl_cb) override { + const std::array<IComposer::Capability, 3> all_caps = {{ + IComposer::Capability::SIDEBAND_STREAM, + IComposer::Capability::SKIP_CLIENT_COLOR_TRANSFORM, + IComposer::Capability::PRESENT_FENCE_IS_NOT_RELIABLE, + }}; + + std::vector<IComposer::Capability> caps; + for (auto cap : all_caps) { + if (mHal->hasCapability(static_cast<hwc2_capability_t>(cap))) { + caps.push_back(cap); + } + } + + hidl_vec<IComposer::Capability> caps_reply; + caps_reply.setToExternal(caps.data(), caps.size()); + hidl_cb(caps_reply); + return Void(); + } + + Return<void> dumpDebugInfo(IComposer::dumpDebugInfo_cb hidl_cb) override { + hidl_cb(mHal->dumpDebugInfo()); + return Void(); + } + + Return<void> createClient(IComposer::createClient_cb hidl_cb) override { + std::unique_lock<std::mutex> lock(mClientMutex); + bool destroyed = waitForClientDestroyedLocked(lock); + if (!destroyed) { + hidl_cb(Error::NO_RESOURCES, nullptr); + return Void(); + } + + sp<IComposerClient> client = createClient(); + if (!client) { + hidl_cb(Error::NO_RESOURCES, nullptr); + return Void(); + } + + mClient = client; + hidl_cb(Error::NONE, client); + return Void(); + } + + protected: + bool waitForClientDestroyedLocked(std::unique_lock<std::mutex>& lock) { + if (mClient != nullptr) { + using namespace std::chrono_literals; + + // In surface flinger we delete a composer client on one thread and + // then create a new client on another thread. Although surface + // flinger ensures the calls are made in that sequence (destroy and + // then create), sometimes the calls land in the composer service + // inverted (create and then destroy). Wait for a brief period to + // see if the existing client is destroyed. + ALOGD("waiting for previous client to be destroyed"); + mClientDestroyedCondition.wait_for(lock, 1s, + [this]() -> bool { return mClient == nullptr; }); + if (mClient != nullptr) { + ALOGD("previous client was not destroyed"); + } + } + + return mClient == nullptr; + } + + void onClientDestroyed() { + std::lock_guard<std::mutex> lock(mClientMutex); + mClient.clear(); + mClientDestroyedCondition.notify_all(); + } + + virtual IComposerClient* createClient() { + auto client = ComposerClient::create(mHal.get()); + if (!client) { + return nullptr; + } + + auto clientDestroyed = [this]() { onClientDestroyed(); }; + client->setOnClientDestroyed(clientDestroyed); + + return client.release(); + } + + const std::unique_ptr<Hal> mHal; + + std::mutex mClientMutex; + wp<IComposerClient> mClient; + std::condition_variable mClientDestroyedCondition; +}; + +} // namespace detail + +using Composer = detail::ComposerImpl<IComposer, ComposerHal>; + +} // namespace hal +} // namespace V2_1 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/service/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h new file mode 100644 index 0000000..095189f --- a/dev/null +++ b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h @@ -0,0 +1,397 @@ +/* + * Copyright 2018 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. + */ + +#pragma once + +#ifndef LOG_TAG +#warning "ComposerClient.h included without LOG_TAG" +#endif + +#include <memory> +#include <mutex> +#include <vector> + +#include <android/hardware/graphics/composer/2.1/IComposerClient.h> +#include <composer-hal/2.1/ComposerCommandEngine.h> +#include <composer-hal/2.1/ComposerHal.h> +#include <composer-hal/2.1/ComposerResources.h> +#include <log/log.h> + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_1 { +namespace hal { + +namespace detail { + +// ComposerClientImpl implements V2_*::IComposerClient on top of V2_*::ComposerHal +template <typename Interface, typename Hal> +class ComposerClientImpl : public Interface { + public: + static std::unique_ptr<ComposerClientImpl> create(Hal* hal) { + auto client = std::make_unique<ComposerClientImpl>(hal); + return client->init() ? std::move(client) : nullptr; + } + + ComposerClientImpl(Hal* hal) : mHal(hal) {} + + virtual ~ComposerClientImpl() { + // not initialized + if (!mCommandEngine) { + return; + } + + ALOGD("destroying composer client"); + + mHal->unregisterEventCallback(); + destroyResources(); + if (mOnClientDestroyed) { + mOnClientDestroyed(); + } + + ALOGD("removed composer client"); + } + + bool init() { + mResources = createResources(); + if (!mResources) { + ALOGE("failed to create composer resources"); + return false; + } + + mCommandEngine = createCommandEngine(); + + return true; + } + + void setOnClientDestroyed(std::function<void()> onClientDestroyed) { + mOnClientDestroyed = onClientDestroyed; + } + + // IComposerClient 2.1 interface + + class HalEventCallback : public Hal::EventCallback { + public: + HalEventCallback(const sp<IComposerCallback> callback, ComposerResources* resources) + : mCallback(callback), mResources(resources) {} + + void onHotplug(Display display, IComposerCallback::Connection connected) { + if (connected == IComposerCallback::Connection::CONNECTED) { + mResources->addPhysicalDisplay(display); + } else if (connected == IComposerCallback::Connection::DISCONNECTED) { + mResources->removeDisplay(display); + } + + auto ret = mCallback->onHotplug(display, connected); + ALOGE_IF(!ret.isOk(), "failed to send onHotplug: %s", ret.description().c_str()); + } + + void onRefresh(Display display) { + mResources->setDisplayMustValidateState(display, true); + auto ret = mCallback->onRefresh(display); + ALOGE_IF(!ret.isOk(), "failed to send onRefresh: %s", ret.description().c_str()); + } + + void onVsync(Display display, int64_t timestamp) { + auto ret = mCallback->onVsync(display, timestamp); + ALOGE_IF(!ret.isOk(), "failed to send onVsync: %s", ret.description().c_str()); + } + + protected: + const sp<IComposerCallback> mCallback; + ComposerResources* const mResources; + }; + + Return<void> registerCallback(const sp<IComposerCallback>& callback) override { + // no locking as we require this function to be called only once + mHalEventCallback = std::make_unique<HalEventCallback>(callback, mResources.get()); + mHal->registerEventCallback(mHalEventCallback.get()); + return Void(); + } + + Return<uint32_t> getMaxVirtualDisplayCount() override { + return mHal->getMaxVirtualDisplayCount(); + } + + Return<void> createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat formatHint, + uint32_t outputBufferSlotCount, + IComposerClient::createVirtualDisplay_cb hidl_cb) override { + Display display = 0; + Error err = mHal->createVirtualDisplay(width, height, &formatHint, &display); + if (err == Error::NONE) { + mResources->addVirtualDisplay(display, outputBufferSlotCount); + } + + hidl_cb(err, display, formatHint); + return Void(); + } + + Return<Error> destroyVirtualDisplay(Display display) override { + Error err = mHal->destroyVirtualDisplay(display); + if (err == Error::NONE) { + mResources->removeDisplay(display); + } + + return err; + } + + Return<void> createLayer(Display display, uint32_t bufferSlotCount, + IComposerClient::createLayer_cb hidl_cb) override { + Layer layer = 0; + Error err = mHal->createLayer(display, &layer); + if (err == Error::NONE) { + err = mResources->addLayer(display, layer, bufferSlotCount); + if (err != Error::NONE) { + // The display entry may have already been removed by onHotplug. + // Note: We do not destroy the layer on this error as the hotplug + // disconnect invalidates the display id. The implementation should + // ensure all layers for the display are destroyed. + layer = 0; + } + } + + hidl_cb(err, layer); + return Void(); + } + + Return<Error> destroyLayer(Display display, Layer layer) override { + Error err = mHal->destroyLayer(display, layer); + if (err == Error::NONE) { + mResources->removeLayer(display, layer); + } + + return err; + } + + Return<void> getActiveConfig(Display display, + IComposerClient::getActiveConfig_cb hidl_cb) override { + Config config = 0; + Error err = mHal->getActiveConfig(display, &config); + hidl_cb(err, config); + return Void(); + } + + Return<Error> getClientTargetSupport(Display display, uint32_t width, uint32_t height, + PixelFormat format, Dataspace dataspace) override { + Error err = mHal->getClientTargetSupport(display, width, height, format, dataspace); + return err; + } + + Return<void> getColorModes(Display display, + IComposerClient::getColorModes_cb hidl_cb) override { + hidl_vec<ColorMode> modes; + Error err = mHal->getColorModes(display, &modes); + hidl_cb(err, modes); + return Void(); + } + + Return<void> getDisplayAttribute(Display display, Config config, + IComposerClient::Attribute attribute, + IComposerClient::getDisplayAttribute_cb hidl_cb) override { + int32_t value = 0; + Error err = mHal->getDisplayAttribute(display, config, attribute, &value); + hidl_cb(err, value); + return Void(); + } + + Return<void> getDisplayConfigs(Display display, + IComposerClient::getDisplayConfigs_cb hidl_cb) override { + hidl_vec<Config> configs; + Error err = mHal->getDisplayConfigs(display, &configs); + hidl_cb(err, configs); + return Void(); + } + + Return<void> getDisplayName(Display display, + IComposerClient::getDisplayName_cb hidl_cb) override { + hidl_string name; + Error err = mHal->getDisplayName(display, &name); + hidl_cb(err, name); + return Void(); + } + + Return<void> getDisplayType(Display display, + IComposerClient::getDisplayType_cb hidl_cb) override { + IComposerClient::DisplayType type = IComposerClient::DisplayType::INVALID; + Error err = mHal->getDisplayType(display, &type); + hidl_cb(err, type); + return Void(); + } + + Return<void> getDozeSupport(Display display, + IComposerClient::getDozeSupport_cb hidl_cb) override { + bool support = false; + Error err = mHal->getDozeSupport(display, &support); + hidl_cb(err, support); + return Void(); + } + + Return<void> getHdrCapabilities(Display display, + IComposerClient::getHdrCapabilities_cb hidl_cb) override { + hidl_vec<Hdr> types; + float max_lumi = 0.0f; + float max_avg_lumi = 0.0f; + float min_lumi = 0.0f; + Error err = mHal->getHdrCapabilities(display, &types, &max_lumi, &max_avg_lumi, &min_lumi); + hidl_cb(err, types, max_lumi, max_avg_lumi, min_lumi); + return Void(); + } + + Return<Error> setActiveConfig(Display display, Config config) override { + Error err = mHal->setActiveConfig(display, config); + return err; + } + + Return<Error> setColorMode(Display display, ColorMode mode) override { + Error err = mHal->setColorMode(display, mode); + return err; + } + + Return<Error> setPowerMode(Display display, IComposerClient::PowerMode mode) override { + Error err = mHal->setPowerMode(display, mode); + return err; + } + + Return<Error> setVsyncEnabled(Display display, IComposerClient::Vsync enabled) override { + Error err = mHal->setVsyncEnabled(display, enabled); + return err; + } + + Return<Error> setClientTargetSlotCount(Display display, + uint32_t clientTargetSlotCount) override { + return mResources->setDisplayClientTargetCacheSize(display, clientTargetSlotCount); + } + + Return<Error> setInputCommandQueue(const MQDescriptorSync<uint32_t>& descriptor) override { + std::lock_guard<std::mutex> lock(mCommandEngineMutex); + return mCommandEngine->setInputMQDescriptor(descriptor) ? Error::NONE : Error::NO_RESOURCES; + } + + Return<void> getOutputCommandQueue(IComposerClient::getOutputCommandQueue_cb hidl_cb) override { + // no locking as we require this function to be called inside + // executeCommands_cb + auto outDescriptor = mCommandEngine->getOutputMQDescriptor(); + if (outDescriptor) { + hidl_cb(Error::NONE, *outDescriptor); + } else { + hidl_cb(Error::NO_RESOURCES, CommandQueueType::Descriptor()); + } + + return Void(); + } + + Return<void> executeCommands(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles, + IComposerClient::executeCommands_cb hidl_cb) override { + std::lock_guard<std::mutex> lock(mCommandEngineMutex); + bool outChanged = false; + uint32_t outLength = 0; + hidl_vec<hidl_handle> outHandles; + Error error = + mCommandEngine->execute(inLength, inHandles, &outChanged, &outLength, &outHandles); + + hidl_cb(error, outChanged, outLength, outHandles); + + mCommandEngine->reset(); + + return Void(); + } + + protected: + virtual std::unique_ptr<ComposerResources> createResources() { + return ComposerResources::create(); + } + + virtual std::unique_ptr<ComposerCommandEngine> createCommandEngine() { + return std::make_unique<ComposerCommandEngine>(mHal, mResources.get()); + } + + void destroyResources() { + // We want to call hwc2_close here (and move hwc2_open to the + // constructor), with the assumption that hwc2_close would + // + // - clean up all resources owned by the client + // - make sure all displays are blank (since there is no layer) + // + // But since SF used to crash at this point, different hwcomposer2 + // implementations behave differently on hwc2_close. Our only portable + // choice really is to abort(). But that is not an option anymore + // because we might also have VTS or VR as clients that can come and go. + // + // Below we manually clean all resources (layers and virtual + // displays), and perform a presentDisplay afterwards. + mResources->clear([this](Display display, bool isVirtual, const std::vector<Layer> layers) { + ALOGW("destroying client resources for display %" PRIu64, display); + + for (auto layer : layers) { + mHal->destroyLayer(display, layer); + } + + if (isVirtual) { + mHal->destroyVirtualDisplay(display); + } else { + ALOGW("performing a final presentDisplay"); + + std::vector<Layer> changedLayers; + std::vector<IComposerClient::Composition> compositionTypes; + uint32_t displayRequestMask = 0; + std::vector<Layer> requestedLayers; + std::vector<uint32_t> requestMasks; + mHal->validateDisplay(display, &changedLayers, &compositionTypes, + &displayRequestMask, &requestedLayers, &requestMasks); + + mHal->acceptDisplayChanges(display); + + int32_t presentFence = -1; + std::vector<Layer> releasedLayers; + std::vector<int32_t> releaseFences; + mHal->presentDisplay(display, &presentFence, &releasedLayers, &releaseFences); + if (presentFence >= 0) { + close(presentFence); + } + for (auto fence : releaseFences) { + if (fence >= 0) { + close(fence); + } + } + } + }); + + mResources.reset(); + } + + Hal* const mHal; + + std::unique_ptr<ComposerResources> mResources; + + std::mutex mCommandEngineMutex; + std::unique_ptr<ComposerCommandEngine> mCommandEngine; + + std::function<void()> mOnClientDestroyed; + std::unique_ptr<HalEventCallback> mHalEventCallback; +}; + +} // namespace detail + +using ComposerClient = detail::ComposerClientImpl<IComposerClient, ComposerHal>; + +} // namespace hal +} // namespace V2_1 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/service/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h new file mode 100644 index 0000000..d87110a --- a/dev/null +++ b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h @@ -0,0 +1,598 @@ +/* + * Copyright 2018 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. + */ + +#pragma once + +#ifndef LOG_TAG +#warning "ComposerCommandEngine.h included without LOG_TAG" +#endif + +#include <vector> + +#include <composer-command-buffer/2.1/ComposerCommandBuffer.h> +#include <composer-hal/2.1/ComposerHal.h> +#include <composer-hal/2.1/ComposerResources.h> +// TODO remove hwcomposer_defs.h dependency +#include <hardware/hwcomposer_defs.h> +#include <log/log.h> + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_1 { +namespace hal { + +// TODO own a CommandReaderBase rather than subclassing +class ComposerCommandEngine : protected CommandReaderBase { + public: + ComposerCommandEngine(ComposerHal* hal, ComposerResources* resources) + : mHal(hal), mResources(resources) {} + + virtual ~ComposerCommandEngine() = default; + + bool setInputMQDescriptor(const MQDescriptorSync<uint32_t>& descriptor) { + return setMQDescriptor(descriptor); + } + + Error execute(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles, bool* outQueueChanged, + uint32_t* outCommandLength, hidl_vec<hidl_handle>* outCommandHandles) { + if (!readQueue(inLength, inHandles)) { + return Error::BAD_PARAMETER; + } + + IComposerClient::Command command; + uint16_t length = 0; + while (!isEmpty()) { + if (!beginCommand(&command, &length)) { + break; + } + + bool parsed = executeCommand(command, length); + endCommand(); + + if (!parsed) { + ALOGE("failed to parse command 0x%x, length %" PRIu16, command, length); + break; + } + } + + if (!isEmpty()) { + return Error::BAD_PARAMETER; + } + + return mWriter.writeQueue(outQueueChanged, outCommandLength, outCommandHandles) + ? Error::NONE + : Error::NO_RESOURCES; + } + + const MQDescriptorSync<uint32_t>* getOutputMQDescriptor() { return mWriter.getMQDescriptor(); } + + void reset() { + CommandReaderBase::reset(); + mWriter.reset(); + } + + protected: + virtual bool executeCommand(IComposerClient::Command command, uint16_t length) { + switch (command) { + case IComposerClient::Command::SELECT_DISPLAY: + return executeSelectDisplay(length); + case IComposerClient::Command::SELECT_LAYER: + return executeSelectLayer(length); + case IComposerClient::Command::SET_COLOR_TRANSFORM: + return executeSetColorTransform(length); + case IComposerClient::Command::SET_CLIENT_TARGET: + return executeSetClientTarget(length); + case IComposerClient::Command::SET_OUTPUT_BUFFER: + return executeSetOutputBuffer(length); + case IComposerClient::Command::VALIDATE_DISPLAY: + return executeValidateDisplay(length); + case IComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY: + return executePresentOrValidateDisplay(length); + case IComposerClient::Command::ACCEPT_DISPLAY_CHANGES: + return executeAcceptDisplayChanges(length); + case IComposerClient::Command::PRESENT_DISPLAY: + return executePresentDisplay(length); + case IComposerClient::Command::SET_LAYER_CURSOR_POSITION: + return executeSetLayerCursorPosition(length); + case IComposerClient::Command::SET_LAYER_BUFFER: + return executeSetLayerBuffer(length); + case IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE: + return executeSetLayerSurfaceDamage(length); + case IComposerClient::Command::SET_LAYER_BLEND_MODE: + return executeSetLayerBlendMode(length); + case IComposerClient::Command::SET_LAYER_COLOR: + return executeSetLayerColor(length); + case IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE: + return executeSetLayerCompositionType(length); + case IComposerClient::Command::SET_LAYER_DATASPACE: + return executeSetLayerDataspace(length); + case IComposerClient::Command::SET_LAYER_DISPLAY_FRAME: + return executeSetLayerDisplayFrame(length); + case IComposerClient::Command::SET_LAYER_PLANE_ALPHA: + return executeSetLayerPlaneAlpha(length); + case IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM: + return executeSetLayerSidebandStream(length); + case IComposerClient::Command::SET_LAYER_SOURCE_CROP: + return executeSetLayerSourceCrop(length); + case IComposerClient::Command::SET_LAYER_TRANSFORM: + return executeSetLayerTransform(length); + case IComposerClient::Command::SET_LAYER_VISIBLE_REGION: + return executeSetLayerVisibleRegion(length); + case IComposerClient::Command::SET_LAYER_Z_ORDER: + return executeSetLayerZOrder(length); + default: + return false; + } + } + + bool executeSelectDisplay(uint16_t length) { + if (length != CommandWriterBase::kSelectDisplayLength) { + return false; + } + + mCurrentDisplay = read64(); + mWriter.selectDisplay(mCurrentDisplay); + + return true; + } + + bool executeSelectLayer(uint16_t length) { + if (length != CommandWriterBase::kSelectLayerLength) { + return false; + } + + mCurrentLayer = read64(); + + return true; + } + + bool executeSetColorTransform(uint16_t length) { + if (length != CommandWriterBase::kSetColorTransformLength) { + return false; + } + + float matrix[16]; + for (int i = 0; i < 16; i++) { + matrix[i] = readFloat(); + } + auto transform = readSigned(); + + auto err = mHal->setColorTransform(mCurrentDisplay, matrix, transform); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + bool executeSetClientTarget(uint16_t length) { + // 4 parameters followed by N rectangles + if ((length - 4) % 4 != 0) { + return false; + } + + bool useCache = false; + auto slot = read(); + auto rawHandle = readHandle(&useCache); + auto fence = readFence(); + auto dataspace = readSigned(); + auto damage = readRegion((length - 4) / 4); + bool closeFence = true; + + const native_handle_t* clientTarget; + ComposerResources::ReplacedBufferHandle replacedClientTarget; + auto err = mResources->getDisplayClientTarget(mCurrentDisplay, slot, useCache, rawHandle, + &clientTarget, &replacedClientTarget); + if (err == Error::NONE) { + err = mHal->setClientTarget(mCurrentDisplay, clientTarget, fence, dataspace, damage); + if (err == Error::NONE) { + closeFence = false; + } + } + if (closeFence) { + close(fence); + } + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + bool executeSetOutputBuffer(uint16_t length) { + if (length != CommandWriterBase::kSetOutputBufferLength) { + return false; + } + + bool useCache = false; + auto slot = read(); + auto rawhandle = readHandle(&useCache); + auto fence = readFence(); + bool closeFence = true; + + const native_handle_t* outputBuffer; + ComposerResources::ReplacedBufferHandle replacedOutputBuffer; + auto err = mResources->getDisplayOutputBuffer(mCurrentDisplay, slot, useCache, rawhandle, + &outputBuffer, &replacedOutputBuffer); + if (err == Error::NONE) { + err = mHal->setOutputBuffer(mCurrentDisplay, outputBuffer, fence); + if (err == Error::NONE) { + closeFence = false; + } + } + if (closeFence) { + close(fence); + } + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + bool executeValidateDisplay(uint16_t length) { + if (length != CommandWriterBase::kValidateDisplayLength) { + return false; + } + + std::vector<Layer> changedLayers; + std::vector<IComposerClient::Composition> compositionTypes; + uint32_t displayRequestMask = 0x0; + std::vector<Layer> requestedLayers; + std::vector<uint32_t> requestMasks; + + auto err = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes, + &displayRequestMask, &requestedLayers, &requestMasks); + mResources->setDisplayMustValidateState(mCurrentDisplay, false); + if (err == Error::NONE) { + mWriter.setChangedCompositionTypes(changedLayers, compositionTypes); + mWriter.setDisplayRequests(displayRequestMask, requestedLayers, requestMasks); + } else { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + bool executePresentOrValidateDisplay(uint16_t length) { + if (length != CommandWriterBase::kPresentOrValidateDisplayLength) { + return false; + } + + // First try to Present as is. + if (mHal->hasCapability(HWC2_CAPABILITY_SKIP_VALIDATE)) { + int presentFence = -1; + std::vector<Layer> layers; + std::vector<int> fences; + auto err = mResources->mustValidateDisplay(mCurrentDisplay) + ? Error::NOT_VALIDATED + : mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences); + if (err == Error::NONE) { + mWriter.setPresentOrValidateResult(1); + mWriter.setPresentFence(presentFence); + mWriter.setReleaseFences(layers, fences); + return true; + } + } + + // Present has failed. We need to fallback to validate + std::vector<Layer> changedLayers; + std::vector<IComposerClient::Composition> compositionTypes; + uint32_t displayRequestMask = 0x0; + std::vector<Layer> requestedLayers; + std::vector<uint32_t> requestMasks; + + auto err = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes, + &displayRequestMask, &requestedLayers, &requestMasks); + mResources->setDisplayMustValidateState(mCurrentDisplay, false); + if (err == Error::NONE) { + mWriter.setPresentOrValidateResult(0); + mWriter.setChangedCompositionTypes(changedLayers, compositionTypes); + mWriter.setDisplayRequests(displayRequestMask, requestedLayers, requestMasks); + } else { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + bool executeAcceptDisplayChanges(uint16_t length) { + if (length != CommandWriterBase::kAcceptDisplayChangesLength) { + return false; + } + + auto err = mHal->acceptDisplayChanges(mCurrentDisplay); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + bool executePresentDisplay(uint16_t length) { + if (length != CommandWriterBase::kPresentDisplayLength) { + return false; + } + + int presentFence = -1; + std::vector<Layer> layers; + std::vector<int> fences; + auto err = mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences); + if (err == Error::NONE) { + mWriter.setPresentFence(presentFence); + mWriter.setReleaseFences(layers, fences); + } else { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + bool executeSetLayerCursorPosition(uint16_t length) { + if (length != CommandWriterBase::kSetLayerCursorPositionLength) { + return false; + } + + auto err = mHal->setLayerCursorPosition(mCurrentDisplay, mCurrentLayer, readSigned(), + readSigned()); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + bool executeSetLayerBuffer(uint16_t length) { + if (length != CommandWriterBase::kSetLayerBufferLength) { + return false; + } + + bool useCache = false; + auto slot = read(); + auto rawHandle = readHandle(&useCache); + auto fence = readFence(); + bool closeFence = true; + + const native_handle_t* buffer; + ComposerResources::ReplacedBufferHandle replacedBuffer; + auto err = mResources->getLayerBuffer(mCurrentDisplay, mCurrentLayer, slot, useCache, + rawHandle, &buffer, &replacedBuffer); + if (err == Error::NONE) { + err = mHal->setLayerBuffer(mCurrentDisplay, mCurrentLayer, buffer, fence); + if (err == Error::NONE) { + closeFence = false; + } + } + if (closeFence) { + close(fence); + } + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + bool executeSetLayerSurfaceDamage(uint16_t length) { + // N rectangles + if (length % 4 != 0) { + return false; + } + + auto damage = readRegion(length / 4); + auto err = mHal->setLayerSurfaceDamage(mCurrentDisplay, mCurrentLayer, damage); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + bool executeSetLayerBlendMode(uint16_t length) { + if (length != CommandWriterBase::kSetLayerBlendModeLength) { + return false; + } + + auto err = mHal->setLayerBlendMode(mCurrentDisplay, mCurrentLayer, readSigned()); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + bool executeSetLayerColor(uint16_t length) { + if (length != CommandWriterBase::kSetLayerColorLength) { + return false; + } + + auto err = mHal->setLayerColor(mCurrentDisplay, mCurrentLayer, readColor()); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + bool executeSetLayerCompositionType(uint16_t length) { + if (length != CommandWriterBase::kSetLayerCompositionTypeLength) { + return false; + } + + auto err = mHal->setLayerCompositionType(mCurrentDisplay, mCurrentLayer, readSigned()); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + bool executeSetLayerDataspace(uint16_t length) { + if (length != CommandWriterBase::kSetLayerDataspaceLength) { + return false; + } + + auto err = mHal->setLayerDataspace(mCurrentDisplay, mCurrentLayer, readSigned()); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + bool executeSetLayerDisplayFrame(uint16_t length) { + if (length != CommandWriterBase::kSetLayerDisplayFrameLength) { + return false; + } + + auto err = mHal->setLayerDisplayFrame(mCurrentDisplay, mCurrentLayer, readRect()); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + bool executeSetLayerPlaneAlpha(uint16_t length) { + if (length != CommandWriterBase::kSetLayerPlaneAlphaLength) { + return false; + } + + auto err = mHal->setLayerPlaneAlpha(mCurrentDisplay, mCurrentLayer, readFloat()); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + bool executeSetLayerSidebandStream(uint16_t length) { + if (length != CommandWriterBase::kSetLayerSidebandStreamLength) { + return false; + } + + auto rawHandle = readHandle(); + + const native_handle_t* stream; + ComposerResources::ReplacedStreamHandle replacedStream; + auto err = mResources->getLayerSidebandStream(mCurrentDisplay, mCurrentLayer, rawHandle, + &stream, &replacedStream); + if (err == Error::NONE) { + err = mHal->setLayerSidebandStream(mCurrentDisplay, mCurrentLayer, stream); + } + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + bool executeSetLayerSourceCrop(uint16_t length) { + if (length != CommandWriterBase::kSetLayerSourceCropLength) { + return false; + } + + auto err = mHal->setLayerSourceCrop(mCurrentDisplay, mCurrentLayer, readFRect()); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + bool executeSetLayerTransform(uint16_t length) { + if (length != CommandWriterBase::kSetLayerTransformLength) { + return false; + } + + auto err = mHal->setLayerTransform(mCurrentDisplay, mCurrentLayer, readSigned()); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + bool executeSetLayerVisibleRegion(uint16_t length) { + // N rectangles + if (length % 4 != 0) { + return false; + } + + auto region = readRegion(length / 4); + auto err = mHal->setLayerVisibleRegion(mCurrentDisplay, mCurrentLayer, region); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + bool executeSetLayerZOrder(uint16_t length) { + if (length != CommandWriterBase::kSetLayerZOrderLength) { + return false; + } + + auto err = mHal->setLayerZOrder(mCurrentDisplay, mCurrentLayer, read()); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + hwc_rect_t readRect() { + return hwc_rect_t{ + readSigned(), readSigned(), readSigned(), readSigned(), + }; + } + + std::vector<hwc_rect_t> readRegion(size_t count) { + std::vector<hwc_rect_t> region; + region.reserve(count); + while (count > 0) { + region.emplace_back(readRect()); + count--; + } + + return region; + } + + hwc_frect_t readFRect() { + return hwc_frect_t{ + readFloat(), readFloat(), readFloat(), readFloat(), + }; + } + + ComposerHal* mHal; + ComposerResources* mResources; + + // 64KiB minus a small space for metadata such as read/write pointers + static constexpr size_t kWriterInitialSize = 64 * 1024 / sizeof(uint32_t) - 16; + CommandWriterBase mWriter{kWriterInitialSize}; + + Display mCurrentDisplay = 0; + Layer mCurrentLayer = 0; +}; + +} // namespace hal +} // namespace V2_1 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/service/2.1/utils/hal/include/composer-hal/2.1/ComposerHal.h b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerHal.h new file mode 100644 index 0000000..c9793fd --- a/dev/null +++ b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerHal.h @@ -0,0 +1,137 @@ +/* + * Copyright 2018 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. + */ + +#pragma once + +#include <string> +#include <vector> + +#include <android/hardware/graphics/composer/2.1/IComposer.h> +#include <android/hardware/graphics/composer/2.1/IComposerClient.h> + +// TODO remove hwcomposer2.h dependency +#define HWC2_INCLUDE_STRINGIFICATION +#define HWC2_USE_CPP11 +#include <hardware/hwcomposer2.h> +#undef HWC2_INCLUDE_STRINGIFICATION +#undef HWC2_USE_CPP11 + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_1 { +namespace hal { + +using common::V1_0::ColorMode; +using common::V1_0::ColorTransform; +using common::V1_0::Dataspace; +using common::V1_0::Hdr; +using common::V1_0::PixelFormat; +using common::V1_0::Transform; + +class ComposerHal { + public: + virtual ~ComposerHal() = default; + + virtual bool hasCapability(hwc2_capability_t capability) = 0; + + // dump the debug information + virtual std::string dumpDebugInfo() = 0; + + class EventCallback { + public: + virtual ~EventCallback() = default; + virtual void onHotplug(Display display, IComposerCallback::Connection connected) = 0; + virtual void onRefresh(Display display) = 0; + virtual void onVsync(Display display, int64_t timestamp) = 0; + }; + + // Register the event callback object. The event callback object is valid + // until it is unregistered. A hotplug event must be generated for each + // connected physical display, before or after this function returns. + virtual void registerEventCallback(EventCallback* callback) = 0; + + // Unregister the event callback object. It must block if there is any + // callback in-flight. + virtual void unregisterEventCallback() = 0; + + virtual uint32_t getMaxVirtualDisplayCount() = 0; + virtual Error createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format, + Display* outDisplay) = 0; + virtual Error destroyVirtualDisplay(Display display) = 0; + virtual Error createLayer(Display display, Layer* outLayer) = 0; + virtual Error destroyLayer(Display display, Layer layer) = 0; + + virtual Error getActiveConfig(Display display, Config* outConfig) = 0; + virtual Error getClientTargetSupport(Display display, uint32_t width, uint32_t height, + PixelFormat format, Dataspace dataspace) = 0; + virtual Error getColorModes(Display display, hidl_vec<ColorMode>* outModes) = 0; + virtual Error getDisplayAttribute(Display display, Config config, + IComposerClient::Attribute attribute, int32_t* outValue) = 0; + virtual Error getDisplayConfigs(Display display, hidl_vec<Config>* outConfigs) = 0; + virtual Error getDisplayName(Display display, hidl_string* outName) = 0; + virtual Error getDisplayType(Display display, IComposerClient::DisplayType* outType) = 0; + virtual Error getDozeSupport(Display display, bool* outSupport) = 0; + virtual Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes, + float* outMaxLuminance, float* outMaxAverageLuminance, + float* outMinLuminance) = 0; + + virtual Error setActiveConfig(Display display, Config config) = 0; + virtual Error setColorMode(Display display, ColorMode mode) = 0; + virtual Error setPowerMode(Display display, IComposerClient::PowerMode mode) = 0; + virtual Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled) = 0; + + virtual Error setColorTransform(Display display, const float* matrix, int32_t hint) = 0; + virtual Error setClientTarget(Display display, buffer_handle_t target, int32_t acquireFence, + int32_t dataspace, const std::vector<hwc_rect_t>& damage) = 0; + virtual Error setOutputBuffer(Display display, buffer_handle_t buffer, + int32_t releaseFence) = 0; + virtual Error validateDisplay(Display display, std::vector<Layer>* outChangedLayers, + std::vector<IComposerClient::Composition>* outCompositionTypes, + uint32_t* outDisplayRequestMask, + std::vector<Layer>* outRequestedLayers, + std::vector<uint32_t>* outRequestMasks) = 0; + virtual Error acceptDisplayChanges(Display display) = 0; + virtual Error presentDisplay(Display display, int32_t* outPresentFence, + std::vector<Layer>* outLayers, + std::vector<int32_t>* outReleaseFences) = 0; + + virtual Error setLayerCursorPosition(Display display, Layer layer, int32_t x, int32_t y) = 0; + virtual Error setLayerBuffer(Display display, Layer layer, buffer_handle_t buffer, + int32_t acquireFence) = 0; + virtual Error setLayerSurfaceDamage(Display display, Layer layer, + const std::vector<hwc_rect_t>& damage) = 0; + virtual Error setLayerBlendMode(Display display, Layer layer, int32_t mode) = 0; + virtual Error setLayerColor(Display display, Layer layer, IComposerClient::Color color) = 0; + virtual Error setLayerCompositionType(Display display, Layer layer, int32_t type) = 0; + virtual Error setLayerDataspace(Display display, Layer layer, int32_t dataspace) = 0; + virtual Error setLayerDisplayFrame(Display display, Layer layer, const hwc_rect_t& frame) = 0; + virtual Error setLayerPlaneAlpha(Display display, Layer layer, float alpha) = 0; + virtual Error setLayerSidebandStream(Display display, Layer layer, buffer_handle_t stream) = 0; + virtual Error setLayerSourceCrop(Display display, Layer layer, const hwc_frect_t& crop) = 0; + virtual Error setLayerTransform(Display display, Layer layer, int32_t transform) = 0; + virtual Error setLayerVisibleRegion(Display display, Layer layer, + const std::vector<hwc_rect_t>& visible) = 0; + virtual Error setLayerZOrder(Display display, Layer layer, uint32_t z) = 0; +}; + +} // namespace hal +} // namespace V2_1 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/service/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h new file mode 100644 index 0000000..18d184e --- a/dev/null +++ b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h @@ -0,0 +1,592 @@ +/* + * Copyright 2018 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. + */ + +#pragma once + +#ifndef LOG_TAG +#warning "ComposerResources.h included without LOG_TAG" +#endif + +#include <memory> +#include <mutex> +#include <unordered_map> +#include <vector> + +#include <android/hardware/graphics/mapper/2.0/IMapper.h> +#include <android/hardware/graphics/mapper/3.0/IMapper.h> +#include <log/log.h> + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_1 { +namespace hal { + +// wrapper for IMapper to import buffers and sideband streams +class ComposerHandleImporter { + public: + bool init() { + mMapper3 = mapper::V3_0::IMapper::getService(); + if (mMapper3) { + return true; + } + ALOGD_IF(!mMapper3, "failed to get mapper 3.0 service, falling back to mapper 2.0"); + + mMapper2 = mapper::V2_0::IMapper::getService(); + ALOGE_IF(!mMapper2, "failed to get mapper 2.0 service"); + + return mMapper2 != nullptr; + } + + Error importBuffer(const native_handle_t* rawHandle, const native_handle_t** outBufferHandle) { + if (!rawHandle || (!rawHandle->numFds && !rawHandle->numInts)) { + *outBufferHandle = nullptr; + return Error::NONE; + } + + const native_handle_t* bufferHandle; + if (mMapper2) { + mapper::V2_0::Error error; + mMapper2->importBuffer( + rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) { + error = tmpError; + bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle); + }); + if (error != mapper::V2_0::Error::NONE) { + return Error::NO_RESOURCES; + } + } + if (mMapper3) { + mapper::V3_0::Error error; + mMapper3->importBuffer( + rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) { + error = tmpError; + bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle); + }); + if (error != mapper::V3_0::Error::NONE) { + return Error::NO_RESOURCES; + } + } + + *outBufferHandle = bufferHandle; + return Error::NONE; + } + + void freeBuffer(const native_handle_t* bufferHandle) { + if (bufferHandle) { + if (mMapper2) { + mMapper2->freeBuffer( + static_cast<void*>(const_cast<native_handle_t*>(bufferHandle))); + } else if (mMapper3) { + mMapper3->freeBuffer( + static_cast<void*>(const_cast<native_handle_t*>(bufferHandle))); + } + } + } + + Error importStream(const native_handle_t* rawHandle, const native_handle_t** outStreamHandle) { + const native_handle_t* streamHandle = nullptr; + if (rawHandle) { + streamHandle = native_handle_clone(rawHandle); + if (!streamHandle) { + return Error::NO_RESOURCES; + } + } + + *outStreamHandle = streamHandle; + return Error::NONE; + } + + void freeStream(const native_handle_t* streamHandle) { + if (streamHandle) { + native_handle_close(streamHandle); + native_handle_delete(const_cast<native_handle_t*>(streamHandle)); + } + } + + private: + sp<mapper::V2_0::IMapper> mMapper2; + sp<mapper::V3_0::IMapper> mMapper3; +}; + +class ComposerHandleCache { + public: + enum class HandleType { + INVALID, + BUFFER, + STREAM, + }; + + ComposerHandleCache(ComposerHandleImporter& importer, HandleType type, uint32_t cacheSize) + : mImporter(importer), mHandleType(type), mHandles(cacheSize, nullptr) {} + + // must be initialized later with initCache + ComposerHandleCache(ComposerHandleImporter& importer) : mImporter(importer) {} + + ~ComposerHandleCache() { + switch (mHandleType) { + case HandleType::BUFFER: + for (auto handle : mHandles) { + mImporter.freeBuffer(handle); + } + break; + case HandleType::STREAM: + for (auto handle : mHandles) { + mImporter.freeStream(handle); + } + break; + default: + break; + } + } + + ComposerHandleCache(const ComposerHandleCache&) = delete; + ComposerHandleCache& operator=(const ComposerHandleCache&) = delete; + + bool initCache(HandleType type, uint32_t cacheSize) { + // already initialized + if (mHandleType != HandleType::INVALID) { + return false; + } + + mHandleType = type; + mHandles.resize(cacheSize, nullptr); + + return true; + } + + Error lookupCache(uint32_t slot, const native_handle_t** outHandle) { + if (slot >= 0 && slot < mHandles.size()) { + *outHandle = mHandles[slot]; + return Error::NONE; + } else { + return Error::BAD_PARAMETER; + } + } + + Error updateCache(uint32_t slot, const native_handle_t* handle, + const native_handle** outReplacedHandle) { + if (slot >= 0 && slot < mHandles.size()) { + auto& cachedHandle = mHandles[slot]; + *outReplacedHandle = cachedHandle; + cachedHandle = handle; + return Error::NONE; + } else { + return Error::BAD_PARAMETER; + } + } + + // when fromCache is true, look up in the cache; otherwise, update the cache + Error getHandle(uint32_t slot, bool fromCache, const native_handle_t* inHandle, + const native_handle_t** outHandle, const native_handle** outReplacedHandle) { + if (fromCache) { + *outReplacedHandle = nullptr; + return lookupCache(slot, outHandle); + } else { + *outHandle = inHandle; + return updateCache(slot, inHandle, outReplacedHandle); + } + } + + private: + ComposerHandleImporter& mImporter; + HandleType mHandleType = HandleType::INVALID; + std::vector<const native_handle_t*> mHandles; +}; + +// layer resource +class ComposerLayerResource { + public: + ComposerLayerResource(ComposerHandleImporter& importer, uint32_t bufferCacheSize) + : mBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, bufferCacheSize), + mSidebandStreamCache(importer, ComposerHandleCache::HandleType::STREAM, 1) {} + + virtual ~ComposerLayerResource() = default; + + Error getBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle, + const native_handle_t** outHandle, const native_handle** outReplacedHandle) { + return mBufferCache.getHandle(slot, fromCache, inHandle, outHandle, outReplacedHandle); + } + + Error getSidebandStream(uint32_t slot, bool fromCache, const native_handle_t* inHandle, + const native_handle_t** outHandle, + const native_handle** outReplacedHandle) { + return mSidebandStreamCache.getHandle(slot, fromCache, inHandle, outHandle, + outReplacedHandle); + } + + protected: + ComposerHandleCache mBufferCache; + ComposerHandleCache mSidebandStreamCache; +}; + +// display resource +class ComposerDisplayResource { + public: + enum class DisplayType { + PHYSICAL, + VIRTUAL, + }; + + virtual ~ComposerDisplayResource() = default; + + ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer, + uint32_t outputBufferCacheSize) + : mType(type), + mClientTargetCache(importer), + mOutputBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, + outputBufferCacheSize), + mMustValidate(true) {} + + bool initClientTargetCache(uint32_t cacheSize) { + return mClientTargetCache.initCache(ComposerHandleCache::HandleType::BUFFER, cacheSize); + } + + bool isVirtual() const { return mType == DisplayType::VIRTUAL; } + + Error getClientTarget(uint32_t slot, bool fromCache, const native_handle_t* inHandle, + const native_handle_t** outHandle, + const native_handle** outReplacedHandle) { + return mClientTargetCache.getHandle(slot, fromCache, inHandle, outHandle, + outReplacedHandle); + } + + Error getOutputBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle, + const native_handle_t** outHandle, + const native_handle** outReplacedHandle) { + return mOutputBufferCache.getHandle(slot, fromCache, inHandle, outHandle, + outReplacedHandle); + } + + bool addLayer(Layer layer, std::unique_ptr<ComposerLayerResource> layerResource) { + auto result = mLayerResources.emplace(layer, std::move(layerResource)); + return result.second; + } + + bool removeLayer(Layer layer) { return mLayerResources.erase(layer) > 0; } + + ComposerLayerResource* findLayerResource(Layer layer) { + auto layerIter = mLayerResources.find(layer); + if (layerIter == mLayerResources.end()) { + return nullptr; + } + + return layerIter->second.get(); + } + + std::vector<Layer> getLayers() const { + std::vector<Layer> layers; + layers.reserve(mLayerResources.size()); + for (const auto& layerKey : mLayerResources) { + layers.push_back(layerKey.first); + } + return layers; + } + + void setMustValidateState(bool mustValidate) { mMustValidate = mustValidate; } + + bool mustValidate() const { return mMustValidate; } + + protected: + const DisplayType mType; + ComposerHandleCache mClientTargetCache; + ComposerHandleCache mOutputBufferCache; + bool mMustValidate; + + std::unordered_map<Layer, std::unique_ptr<ComposerLayerResource>> mLayerResources; +}; + +class ComposerResources { + private: + template <bool isBuffer> + class ReplacedHandle; + + public: + static std::unique_ptr<ComposerResources> create() { + auto resources = std::make_unique<ComposerResources>(); + return resources->init() ? std::move(resources) : nullptr; + } + + ComposerResources() = default; + virtual ~ComposerResources() = default; + + bool init() { return mImporter.init(); } + + using RemoveDisplay = + std::function<void(Display display, bool isVirtual, const std::vector<Layer>& layers)>; + void clear(RemoveDisplay removeDisplay) { + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + for (const auto& displayKey : mDisplayResources) { + Display display = displayKey.first; + const ComposerDisplayResource& displayResource = *displayKey.second; + removeDisplay(display, displayResource.isVirtual(), displayResource.getLayers()); + } + mDisplayResources.clear(); + } + + Error addPhysicalDisplay(Display display) { + auto displayResource = + createDisplayResource(ComposerDisplayResource::DisplayType::PHYSICAL, 0); + + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + auto result = mDisplayResources.emplace(display, std::move(displayResource)); + return result.second ? Error::NONE : Error::BAD_DISPLAY; + } + + Error addVirtualDisplay(Display display, uint32_t outputBufferCacheSize) { + auto displayResource = createDisplayResource(ComposerDisplayResource::DisplayType::VIRTUAL, + outputBufferCacheSize); + + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + auto result = mDisplayResources.emplace(display, std::move(displayResource)); + return result.second ? Error::NONE : Error::BAD_DISPLAY; + } + + Error removeDisplay(Display display) { + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + return mDisplayResources.erase(display) > 0 ? Error::NONE : Error::BAD_DISPLAY; + } + + Error setDisplayClientTargetCacheSize(Display display, uint32_t clientTargetCacheSize) { + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); + if (!displayResource) { + return Error::BAD_DISPLAY; + } + + return displayResource->initClientTargetCache(clientTargetCacheSize) ? Error::NONE + : Error::BAD_PARAMETER; + } + + Error addLayer(Display display, Layer layer, uint32_t bufferCacheSize) { + auto layerResource = createLayerResource(bufferCacheSize); + + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); + if (!displayResource) { + return Error::BAD_DISPLAY; + } + + return displayResource->addLayer(layer, std::move(layerResource)) ? Error::NONE + : Error::BAD_LAYER; + } + + Error removeLayer(Display display, Layer layer) { + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); + if (!displayResource) { + return Error::BAD_DISPLAY; + } + + return displayResource->removeLayer(layer) ? Error::NONE : Error::BAD_LAYER; + } + + using ReplacedBufferHandle = ReplacedHandle<true>; + using ReplacedStreamHandle = ReplacedHandle<false>; + + Error getDisplayClientTarget(Display display, uint32_t slot, bool fromCache, + const native_handle_t* rawHandle, + const native_handle_t** outBufferHandle, + ReplacedBufferHandle* outReplacedBuffer) { + return getHandle<Cache::CLIENT_TARGET>(display, 0, slot, fromCache, rawHandle, + outBufferHandle, outReplacedBuffer); + } + + Error getDisplayOutputBuffer(Display display, uint32_t slot, bool fromCache, + const native_handle_t* rawHandle, + const native_handle_t** outBufferHandle, + ReplacedBufferHandle* outReplacedBuffer) { + return getHandle<Cache::OUTPUT_BUFFER>(display, 0, slot, fromCache, rawHandle, + outBufferHandle, outReplacedBuffer); + } + + Error getLayerBuffer(Display display, Layer layer, uint32_t slot, bool fromCache, + const native_handle_t* rawHandle, const native_handle_t** outBufferHandle, + ReplacedBufferHandle* outReplacedBuffer) { + return getHandle<Cache::LAYER_BUFFER>(display, layer, slot, fromCache, rawHandle, + outBufferHandle, outReplacedBuffer); + } + + Error getLayerSidebandStream(Display display, Layer layer, const native_handle_t* rawHandle, + const native_handle_t** outStreamHandle, + ReplacedStreamHandle* outReplacedStream) { + return getHandle<Cache::LAYER_SIDEBAND_STREAM>(display, layer, 0, false, rawHandle, + outStreamHandle, outReplacedStream); + } + + void setDisplayMustValidateState(Display display, bool mustValidate) { + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + auto* displayResource = findDisplayResourceLocked(display); + if (displayResource) { + displayResource->setMustValidateState(mustValidate); + } + } + + bool mustValidateDisplay(Display display) { + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + auto* displayResource = findDisplayResourceLocked(display); + if (displayResource) { + return displayResource->mustValidate(); + } + return false; + } + + protected: + virtual std::unique_ptr<ComposerDisplayResource> createDisplayResource( + ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) { + return std::make_unique<ComposerDisplayResource>(type, mImporter, outputBufferCacheSize); + } + + virtual std::unique_ptr<ComposerLayerResource> createLayerResource(uint32_t bufferCacheSize) { + return std::make_unique<ComposerLayerResource>(mImporter, bufferCacheSize); + } + + ComposerDisplayResource* findDisplayResourceLocked(Display display) { + auto iter = mDisplayResources.find(display); + if (iter == mDisplayResources.end()) { + return nullptr; + } + return iter->second.get(); + } + + ComposerHandleImporter mImporter; + + std::mutex mDisplayResourcesMutex; + std::unordered_map<Display, std::unique_ptr<ComposerDisplayResource>> mDisplayResources; + + private: + enum class Cache { + CLIENT_TARGET, + OUTPUT_BUFFER, + LAYER_BUFFER, + LAYER_SIDEBAND_STREAM, + }; + + // When a buffer in the cache is replaced by a new one, we must keep it + // alive until it has been replaced in ComposerHal. + template <bool isBuffer> + class ReplacedHandle { + public: + ReplacedHandle() = default; + ReplacedHandle(const ReplacedHandle&) = delete; + ReplacedHandle& operator=(const ReplacedHandle&) = delete; + + ~ReplacedHandle() { reset(); } + + void reset(ComposerHandleImporter* importer = nullptr, + const native_handle_t* handle = nullptr) { + if (mHandle) { + if (isBuffer) { + mImporter->freeBuffer(mHandle); + } else { + mImporter->freeStream(mHandle); + } + } + + mImporter = importer; + mHandle = handle; + } + + private: + ComposerHandleImporter* mImporter = nullptr; + const native_handle_t* mHandle = nullptr; + }; + + template <Cache cache, bool isBuffer> + Error getHandle(Display display, Layer layer, uint32_t slot, bool fromCache, + const native_handle_t* rawHandle, const native_handle_t** outHandle, + ReplacedHandle<isBuffer>* outReplacedHandle) { + Error error; + + // import the raw handle (or ignore raw handle when fromCache is true) + const native_handle_t* importedHandle = nullptr; + if (!fromCache) { + error = (isBuffer) ? mImporter.importBuffer(rawHandle, &importedHandle) + : mImporter.importStream(rawHandle, &importedHandle); + if (error != Error::NONE) { + return error; + } + } + + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + + // find display/layer resource + const bool needLayerResource = + (cache == Cache::LAYER_BUFFER || cache == Cache::LAYER_SIDEBAND_STREAM); + ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); + ComposerLayerResource* layerResource = (displayResource && needLayerResource) + ? displayResource->findLayerResource(layer) + : nullptr; + + // lookup or update cache + const native_handle_t* replacedHandle = nullptr; + if (displayResource && (!needLayerResource || layerResource)) { + switch (cache) { + case Cache::CLIENT_TARGET: + error = displayResource->getClientTarget(slot, fromCache, importedHandle, + outHandle, &replacedHandle); + break; + case Cache::OUTPUT_BUFFER: + error = displayResource->getOutputBuffer(slot, fromCache, importedHandle, + outHandle, &replacedHandle); + break; + case Cache::LAYER_BUFFER: + error = layerResource->getBuffer(slot, fromCache, importedHandle, outHandle, + &replacedHandle); + break; + case Cache::LAYER_SIDEBAND_STREAM: + error = layerResource->getSidebandStream(slot, fromCache, importedHandle, + outHandle, &replacedHandle); + break; + default: + error = Error::BAD_PARAMETER; + break; + } + + if (error != Error::NONE) { + ALOGW("invalid cache %d slot %d", int(cache), int(slot)); + } + } else if (!displayResource) { + error = Error::BAD_DISPLAY; + } else { + error = Error::BAD_LAYER; + } + + // clean up on errors + if (error != Error::NONE) { + if (!fromCache) { + if (isBuffer) { + mImporter.freeBuffer(importedHandle); + } else { + mImporter.freeStream(importedHandle); + } + } + return error; + } + + outReplacedHandle->reset(&mImporter, replacedHandle); + + return Error::NONE; + } +}; + +} // namespace hal +} // namespace V2_1 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/service/2.1/utils/passthrough/Android.bp b/service/2.1/utils/passthrough/Android.bp new file mode 100644 index 0000000..4d3c976 --- a/dev/null +++ b/service/2.1/utils/passthrough/Android.bp @@ -0,0 +1,22 @@ +cc_library_headers { + name: "android.hardware.graphics.composer@2.1-passthrough", + defaults: ["hidl_defaults"], + vendor: true, + shared_libs: [ + "libhardware", + "libhwc2on1adapter", + "libhwc2onfbadapter", + ], + export_shared_lib_headers: [ + "libhardware", + "libhwc2on1adapter", + "libhwc2onfbadapter", + ], + header_libs: [ + "android.hardware.graphics.composer@2.1-hal", + ], + export_header_lib_headers: [ + "android.hardware.graphics.composer@2.1-hal", + ], + export_include_dirs: ["include"], +} diff --git a/service/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h b/service/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h new file mode 100644 index 0000000..5826b12 --- a/dev/null +++ b/service/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h @@ -0,0 +1,679 @@ +/* + * Copyright 2016 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. + */ + +#pragma once + +#ifndef LOG_TAG +#warning "HwcHal.h included without LOG_TAG" +#endif + +#include <atomic> +#include <cstring> // for strerror +#include <type_traits> +#include <unordered_set> +#include <vector> + +#include <android/hardware/graphics/composer/2.1/IComposer.h> +#include <composer-hal/2.1/ComposerHal.h> +#define HWC2_INCLUDE_STRINGIFICATION +#define HWC2_USE_CPP11 +#include <hardware/hwcomposer2.h> +#undef HWC2_INCLUDE_STRINGIFICATION +#undef HWC2_USE_CPP11 +#include <log/log.h> + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_1 { +namespace passthrough { + +namespace detail { + +using android::hardware::graphics::common::V1_0::ColorMode; +using android::hardware::graphics::common::V1_0::ColorTransform; +using android::hardware::graphics::common::V1_0::Dataspace; +using android::hardware::graphics::common::V1_0::Hdr; +using android::hardware::graphics::common::V1_0::PixelFormat; +using android::hardware::graphics::common::V1_0::Transform; + +// HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2 +template <typename Hal> +class HwcHalImpl : public Hal { + public: + virtual ~HwcHalImpl() { + if (mDevice) { + hwc2_close(mDevice); + } + } + + bool initWithModule(const hw_module_t* module) { + hwc2_device_t* device; + int result = hwc2_open(module, &device); + if (result) { + ALOGE("failed to open hwcomposer2 device: %s", strerror(-result)); + return false; + } + + return initWithDevice(std::move(device), true); + } + + bool initWithDevice(hwc2_device_t* device, bool requireReliablePresentFence) { + // we own the device from this point on + mDevice = device; + + initCapabilities(); + if (requireReliablePresentFence && + hasCapability(HWC2_CAPABILITY_PRESENT_FENCE_IS_NOT_RELIABLE)) { + ALOGE("present fence must be reliable"); + mDevice->common.close(&mDevice->common); + mDevice = nullptr; + return false; + } + + if (!initDispatch()) { + mDevice->common.close(&mDevice->common); + mDevice = nullptr; + return false; + } + + return true; + } + + bool hasCapability(hwc2_capability_t capability) override { + return (mCapabilities.count(capability) > 0); + } + + std::string dumpDebugInfo() override { + uint32_t len = 0; + mDispatch.dump(mDevice, &len, nullptr); + + std::vector<char> buf(len + 1); + mDispatch.dump(mDevice, &len, buf.data()); + buf.resize(len + 1); + buf[len] = '\0'; + + return buf.data(); + } + + void registerEventCallback(hal::ComposerHal::EventCallback* callback) override { + mEventCallback = callback; + + mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this, + reinterpret_cast<hwc2_function_pointer_t>(hotplugHook)); + mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this, + reinterpret_cast<hwc2_function_pointer_t>(refreshHook)); + mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this, + reinterpret_cast<hwc2_function_pointer_t>(vsyncHook)); + } + + void unregisterEventCallback() override { + // we assume the callback functions + // + // - can be unregistered + // - can be in-flight + // - will never be called afterward + // + // which is likely incorrect + mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this, nullptr); + mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this, nullptr); + mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this, nullptr); + + mEventCallback = nullptr; + } + + uint32_t getMaxVirtualDisplayCount() override { + return mDispatch.getMaxVirtualDisplayCount(mDevice); + } + + Error createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format, + Display* outDisplay) override { + int32_t hwc_format = static_cast<int32_t>(*format); + int32_t err = + mDispatch.createVirtualDisplay(mDevice, width, height, &hwc_format, outDisplay); + *format = static_cast<PixelFormat>(hwc_format); + + return static_cast<Error>(err); + } + + Error destroyVirtualDisplay(Display display) override { + int32_t err = mDispatch.destroyVirtualDisplay(mDevice, display); + return static_cast<Error>(err); + } + + Error createLayer(Display display, Layer* outLayer) override { + int32_t err = mDispatch.createLayer(mDevice, display, outLayer); + return static_cast<Error>(err); + } + + Error destroyLayer(Display display, Layer layer) override { + int32_t err = mDispatch.destroyLayer(mDevice, display, layer); + onLayerDestroyed(display, layer); + return static_cast<Error>(err); + } + + Error getActiveConfig(Display display, Config* outConfig) override { + int32_t err = mDispatch.getActiveConfig(mDevice, display, outConfig); + return static_cast<Error>(err); + } + + Error getClientTargetSupport(Display display, uint32_t width, uint32_t height, + PixelFormat format, Dataspace dataspace) override { + int32_t err = mDispatch.getClientTargetSupport(mDevice, display, width, height, + static_cast<int32_t>(format), + static_cast<int32_t>(dataspace)); + return static_cast<Error>(err); + } + + Error getColorModes(Display display, hidl_vec<ColorMode>* outModes) override { + uint32_t count = 0; + int32_t err = mDispatch.getColorModes(mDevice, display, &count, nullptr); + if (err != HWC2_ERROR_NONE) { + return static_cast<Error>(err); + } + + outModes->resize(count); + err = mDispatch.getColorModes( + mDevice, display, &count, + reinterpret_cast<std::underlying_type<ColorMode>::type*>(outModes->data())); + if (err != HWC2_ERROR_NONE) { + *outModes = hidl_vec<ColorMode>(); + return static_cast<Error>(err); + } + + return Error::NONE; + } + + Error getDisplayAttribute(Display display, Config config, IComposerClient::Attribute attribute, + int32_t* outValue) override { + int32_t err = mDispatch.getDisplayAttribute(mDevice, display, config, + static_cast<int32_t>(attribute), outValue); + return static_cast<Error>(err); + } + + Error getDisplayConfigs(Display display, hidl_vec<Config>* outConfigs) override { + uint32_t count = 0; + int32_t err = mDispatch.getDisplayConfigs(mDevice, display, &count, nullptr); + if (err != HWC2_ERROR_NONE) { + return static_cast<Error>(err); + } + + outConfigs->resize(count); + err = mDispatch.getDisplayConfigs(mDevice, display, &count, outConfigs->data()); + if (err != HWC2_ERROR_NONE) { + *outConfigs = hidl_vec<Config>(); + return static_cast<Error>(err); + } + + return Error::NONE; + } + + Error getDisplayName(Display display, hidl_string* outName) override { + uint32_t count = 0; + int32_t err = mDispatch.getDisplayName(mDevice, display, &count, nullptr); + if (err != HWC2_ERROR_NONE) { + return static_cast<Error>(err); + } + + std::vector<char> buf(count + 1); + err = mDispatch.getDisplayName(mDevice, display, &count, buf.data()); + if (err != HWC2_ERROR_NONE) { + return static_cast<Error>(err); + } + buf.resize(count + 1); + buf[count] = '\0'; + + *outName = buf.data(); + + return Error::NONE; + } + + Error getDisplayType(Display display, IComposerClient::DisplayType* outType) override { + int32_t hwc_type = HWC2_DISPLAY_TYPE_INVALID; + int32_t err = mDispatch.getDisplayType(mDevice, display, &hwc_type); + *outType = static_cast<IComposerClient::DisplayType>(hwc_type); + + return static_cast<Error>(err); + } + + Error getDozeSupport(Display display, bool* outSupport) override { + int32_t hwc_support = 0; + int32_t err = mDispatch.getDozeSupport(mDevice, display, &hwc_support); + *outSupport = hwc_support; + + return static_cast<Error>(err); + } + + Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes, float* outMaxLuminance, + float* outMaxAverageLuminance, float* outMinLuminance) override { + uint32_t count = 0; + int32_t err = + mDispatch.getHdrCapabilities(mDevice, display, &count, nullptr, outMaxLuminance, + outMaxAverageLuminance, outMinLuminance); + if (err != HWC2_ERROR_NONE) { + return static_cast<Error>(err); + } + + outTypes->resize(count); + err = mDispatch.getHdrCapabilities( + mDevice, display, &count, + reinterpret_cast<std::underlying_type<Hdr>::type*>(outTypes->data()), outMaxLuminance, + outMaxAverageLuminance, outMinLuminance); + if (err != HWC2_ERROR_NONE) { + *outTypes = hidl_vec<Hdr>(); + return static_cast<Error>(err); + } + + return Error::NONE; + } + + Error setActiveConfig(Display display, Config config) override { + int32_t err = mDispatch.setActiveConfig(mDevice, display, config); + return static_cast<Error>(err); + } + + Error setColorMode(Display display, ColorMode mode) override { + int32_t err = mDispatch.setColorMode(mDevice, display, static_cast<int32_t>(mode)); + return static_cast<Error>(err); + } + + Error setPowerMode(Display display, IComposerClient::PowerMode mode) override { + int32_t err = mDispatch.setPowerMode(mDevice, display, static_cast<int32_t>(mode)); + return static_cast<Error>(err); + } + + Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled) override { + int32_t err = mDispatch.setVsyncEnabled(mDevice, display, static_cast<int32_t>(enabled)); + return static_cast<Error>(err); + } + + Error setColorTransform(Display display, const float* matrix, int32_t hint) override { + int32_t err = mDispatch.setColorTransform(mDevice, display, matrix, hint); + return static_cast<Error>(err); + } + + Error setClientTarget(Display display, buffer_handle_t target, int32_t acquireFence, + int32_t dataspace, const std::vector<hwc_rect_t>& damage) override { + hwc_region region = {damage.size(), damage.data()}; + int32_t err = + mDispatch.setClientTarget(mDevice, display, target, acquireFence, dataspace, region); + return static_cast<Error>(err); + } + + Error setOutputBuffer(Display display, buffer_handle_t buffer, int32_t releaseFence) override { + int32_t err = mDispatch.setOutputBuffer(mDevice, display, buffer, releaseFence); + // unlike in setClientTarget, releaseFence is owned by us + if (err == HWC2_ERROR_NONE && releaseFence >= 0) { + close(releaseFence); + } + + return static_cast<Error>(err); + } + + Error validateDisplay(Display display, std::vector<Layer>* outChangedLayers, + std::vector<IComposerClient::Composition>* outCompositionTypes, + uint32_t* outDisplayRequestMask, std::vector<Layer>* outRequestedLayers, + std::vector<uint32_t>* outRequestMasks) override { + onBeforeValidateDisplay(display); + uint32_t typesCount = 0; + uint32_t reqsCount = 0; + int32_t err = mDispatch.validateDisplay(mDevice, display, &typesCount, &reqsCount); + + if (err != HWC2_ERROR_NONE && err != HWC2_ERROR_HAS_CHANGES) { + return static_cast<Error>(err); + } + + err = getChangedCompositionTypes(display, &typesCount, nullptr, nullptr); + if (err != HWC2_ERROR_NONE) { + return static_cast<Error>(err); + } + + std::vector<Layer> changedLayers(typesCount); + std::vector<IComposerClient::Composition> compositionTypes(typesCount); + err = getChangedCompositionTypes(display, &typesCount, changedLayers.data(), + compositionTypes.data()); + if (err != HWC2_ERROR_NONE) { + return static_cast<Error>(err); + } + + int32_t displayReqs = 0; + err = mDispatch.getDisplayRequests(mDevice, display, &displayReqs, &reqsCount, nullptr, + nullptr); + if (err != HWC2_ERROR_NONE) { + return static_cast<Error>(err); + } + + std::vector<Layer> requestedLayers(reqsCount); + std::vector<uint32_t> requestMasks(reqsCount); + err = mDispatch.getDisplayRequests(mDevice, display, &displayReqs, &reqsCount, + requestedLayers.data(), + reinterpret_cast<int32_t*>(requestMasks.data())); + if (err != HWC2_ERROR_NONE) { + return static_cast<Error>(err); + } + + *outChangedLayers = std::move(changedLayers); + *outCompositionTypes = std::move(compositionTypes); + *outDisplayRequestMask = displayReqs; + *outRequestedLayers = std::move(requestedLayers); + *outRequestMasks = std::move(requestMasks); + + return static_cast<Error>(err); + } + + Error acceptDisplayChanges(Display display) override { + int32_t err = mDispatch.acceptDisplayChanges(mDevice, display); + return static_cast<Error>(err); + } + + Error presentDisplay(Display display, int32_t* outPresentFence, std::vector<Layer>* outLayers, + std::vector<int32_t>* outReleaseFences) override { + *outPresentFence = -1; + int32_t err = mDispatch.presentDisplay(mDevice, display, outPresentFence); + if (err != HWC2_ERROR_NONE) { + return static_cast<Error>(err); + } + + uint32_t count = 0; + err = mDispatch.getReleaseFences(mDevice, display, &count, nullptr, nullptr); + if (err != HWC2_ERROR_NONE) { + ALOGW("failed to get release fences"); + return Error::NONE; + } + + outLayers->resize(count); + outReleaseFences->resize(count); + err = mDispatch.getReleaseFences(mDevice, display, &count, outLayers->data(), + outReleaseFences->data()); + if (err != HWC2_ERROR_NONE) { + ALOGW("failed to get release fences"); + outLayers->clear(); + outReleaseFences->clear(); + return Error::NONE; + } + + return static_cast<Error>(err); + } + + Error setLayerCursorPosition(Display display, Layer layer, int32_t x, int32_t y) override { + int32_t err = mDispatch.setCursorPosition(mDevice, display, layer, x, y); + return static_cast<Error>(err); + } + + Error setLayerBuffer(Display display, Layer layer, buffer_handle_t buffer, + int32_t acquireFence) override { + int32_t err = mDispatch.setLayerBuffer(mDevice, display, layer, buffer, acquireFence); + return static_cast<Error>(err); + } + + Error setLayerSurfaceDamage(Display display, Layer layer, + const std::vector<hwc_rect_t>& damage) override { + hwc_region region = {damage.size(), damage.data()}; + int32_t err = mDispatch.setLayerSurfaceDamage(mDevice, display, layer, region); + return static_cast<Error>(err); + } + + Error setLayerBlendMode(Display display, Layer layer, int32_t mode) override { + int32_t err = mDispatch.setLayerBlendMode(mDevice, display, layer, mode); + return static_cast<Error>(err); + } + + Error setLayerColor(Display display, Layer layer, IComposerClient::Color color) override { + hwc_color_t hwc_color{color.r, color.g, color.b, color.a}; + int32_t err = mDispatch.setLayerColor(mDevice, display, layer, hwc_color); + return static_cast<Error>(err); + } + + Error setLayerCompositionType(Display display, Layer layer, int32_t type) override { + int32_t err = mDispatch.setLayerCompositionType(mDevice, display, layer, type); + return static_cast<Error>(err); + } + + Error setLayerDataspace(Display display, Layer layer, int32_t dataspace) override { + int32_t err = mDispatch.setLayerDataspace(mDevice, display, layer, dataspace); + return static_cast<Error>(err); + } + + Error setLayerDisplayFrame(Display display, Layer layer, const hwc_rect_t& frame) override { + int32_t err = mDispatch.setLayerDisplayFrame(mDevice, display, layer, frame); + return static_cast<Error>(err); + } + + Error setLayerPlaneAlpha(Display display, Layer layer, float alpha) override { + int32_t err = mDispatch.setLayerPlaneAlpha(mDevice, display, layer, alpha); + return static_cast<Error>(err); + } + + Error setLayerSidebandStream(Display display, Layer layer, buffer_handle_t stream) override { + int32_t err = mDispatch.setLayerSidebandStream(mDevice, display, layer, stream); + return static_cast<Error>(err); + } + + Error setLayerSourceCrop(Display display, Layer layer, const hwc_frect_t& crop) override { + int32_t err = mDispatch.setLayerSourceCrop(mDevice, display, layer, crop); + return static_cast<Error>(err); + } + + Error setLayerTransform(Display display, Layer layer, int32_t transform) override { + int32_t err = mDispatch.setLayerTransform(mDevice, display, layer, transform); + return static_cast<Error>(err); + } + + Error setLayerVisibleRegion(Display display, Layer layer, + const std::vector<hwc_rect_t>& visible) override { + hwc_region_t region = {visible.size(), visible.data()}; + int32_t err = mDispatch.setLayerVisibleRegion(mDevice, display, layer, region); + return static_cast<Error>(err); + } + + Error setLayerZOrder(Display display, Layer layer, uint32_t z) override { + int32_t err = mDispatch.setLayerZOrder(mDevice, display, layer, z); + return static_cast<Error>(err); + } + + protected: + virtual void initCapabilities() { + uint32_t count = 0; + mDevice->getCapabilities(mDevice, &count, nullptr); + + std::vector<int32_t> caps(count); + mDevice->getCapabilities(mDevice, &count, caps.data()); + caps.resize(count); + + mCapabilities.reserve(count); + for (auto cap : caps) { + mCapabilities.insert(static_cast<hwc2_capability_t>(cap)); + } + } + + template <typename T> + bool initDispatch(hwc2_function_descriptor_t desc, T* outPfn) { + auto pfn = mDevice->getFunction(mDevice, desc); + if (pfn) { + *outPfn = reinterpret_cast<T>(pfn); + return true; + } else { + ALOGE("failed to get hwcomposer2 function %d", desc); + return false; + } + } + + virtual bool initDispatch() { + if (!initDispatch(HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES, &mDispatch.acceptDisplayChanges) || + !initDispatch(HWC2_FUNCTION_CREATE_LAYER, &mDispatch.createLayer) || + !initDispatch(HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY, &mDispatch.createVirtualDisplay) || + !initDispatch(HWC2_FUNCTION_DESTROY_LAYER, &mDispatch.destroyLayer) || + !initDispatch(HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY, + &mDispatch.destroyVirtualDisplay) || + !initDispatch(HWC2_FUNCTION_DUMP, &mDispatch.dump) || + !initDispatch(HWC2_FUNCTION_GET_ACTIVE_CONFIG, &mDispatch.getActiveConfig) || + !initDispatch(HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES, + &mDispatch.getChangedCompositionTypes) || + !initDispatch(HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT, + &mDispatch.getClientTargetSupport) || + !initDispatch(HWC2_FUNCTION_GET_COLOR_MODES, &mDispatch.getColorModes) || + !initDispatch(HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE, &mDispatch.getDisplayAttribute) || + !initDispatch(HWC2_FUNCTION_GET_DISPLAY_CONFIGS, &mDispatch.getDisplayConfigs) || + !initDispatch(HWC2_FUNCTION_GET_DISPLAY_NAME, &mDispatch.getDisplayName) || + !initDispatch(HWC2_FUNCTION_GET_DISPLAY_REQUESTS, &mDispatch.getDisplayRequests) || + !initDispatch(HWC2_FUNCTION_GET_DISPLAY_TYPE, &mDispatch.getDisplayType) || + !initDispatch(HWC2_FUNCTION_GET_DOZE_SUPPORT, &mDispatch.getDozeSupport) || + !initDispatch(HWC2_FUNCTION_GET_HDR_CAPABILITIES, &mDispatch.getHdrCapabilities) || + !initDispatch(HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT, + &mDispatch.getMaxVirtualDisplayCount) || + !initDispatch(HWC2_FUNCTION_GET_RELEASE_FENCES, &mDispatch.getReleaseFences) || + !initDispatch(HWC2_FUNCTION_PRESENT_DISPLAY, &mDispatch.presentDisplay) || + !initDispatch(HWC2_FUNCTION_REGISTER_CALLBACK, &mDispatch.registerCallback) || + !initDispatch(HWC2_FUNCTION_SET_ACTIVE_CONFIG, &mDispatch.setActiveConfig) || + !initDispatch(HWC2_FUNCTION_SET_CLIENT_TARGET, &mDispatch.setClientTarget) || + !initDispatch(HWC2_FUNCTION_SET_COLOR_MODE, &mDispatch.setColorMode) || + !initDispatch(HWC2_FUNCTION_SET_COLOR_TRANSFORM, &mDispatch.setColorTransform) || + !initDispatch(HWC2_FUNCTION_SET_CURSOR_POSITION, &mDispatch.setCursorPosition) || + !initDispatch(HWC2_FUNCTION_SET_LAYER_BLEND_MODE, &mDispatch.setLayerBlendMode) || + !initDispatch(HWC2_FUNCTION_SET_LAYER_BUFFER, &mDispatch.setLayerBuffer) || + !initDispatch(HWC2_FUNCTION_SET_LAYER_COLOR, &mDispatch.setLayerColor) || + !initDispatch(HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE, + &mDispatch.setLayerCompositionType) || + !initDispatch(HWC2_FUNCTION_SET_LAYER_DATASPACE, &mDispatch.setLayerDataspace) || + !initDispatch(HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME, &mDispatch.setLayerDisplayFrame) || + !initDispatch(HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA, &mDispatch.setLayerPlaneAlpha)) { + return false; + } + + if (hasCapability(HWC2_CAPABILITY_SIDEBAND_STREAM)) { + if (!initDispatch(HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM, + &mDispatch.setLayerSidebandStream)) { + return false; + } + } + + if (!initDispatch(HWC2_FUNCTION_SET_LAYER_SOURCE_CROP, &mDispatch.setLayerSourceCrop) || + !initDispatch(HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE, + &mDispatch.setLayerSurfaceDamage) || + !initDispatch(HWC2_FUNCTION_SET_LAYER_TRANSFORM, &mDispatch.setLayerTransform) || + !initDispatch(HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION, + &mDispatch.setLayerVisibleRegion) || + !initDispatch(HWC2_FUNCTION_SET_LAYER_Z_ORDER, &mDispatch.setLayerZOrder) || + !initDispatch(HWC2_FUNCTION_SET_OUTPUT_BUFFER, &mDispatch.setOutputBuffer) || + !initDispatch(HWC2_FUNCTION_SET_POWER_MODE, &mDispatch.setPowerMode) || + !initDispatch(HWC2_FUNCTION_SET_VSYNC_ENABLED, &mDispatch.setVsyncEnabled) || + !initDispatch(HWC2_FUNCTION_VALIDATE_DISPLAY, &mDispatch.validateDisplay)) { + return false; + } + + return true; + } + + virtual int32_t getChangedCompositionTypes(Display display, uint32_t* outTypesCount, + Layer* outChangedLayers, + IComposerClient::Composition* outCompositionTypes) { + return getChangedCompositionTypesInternal(display, outTypesCount, outChangedLayers, + outCompositionTypes); + } + virtual void onLayerDestroyed(Display /* display */, Layer /* layer */) {} + virtual void onBeforeValidateDisplay(Display /* display */) {} + + static void hotplugHook(hwc2_callback_data_t callbackData, hwc2_display_t display, + int32_t connected) { + auto hal = static_cast<HwcHalImpl*>(callbackData); + hal->mEventCallback->onHotplug(display, + static_cast<IComposerCallback::Connection>(connected)); + } + + static void refreshHook(hwc2_callback_data_t callbackData, hwc2_display_t display) { + auto hal = static_cast<HwcHalImpl*>(callbackData); + hal->mEventCallback->onRefresh(display); + } + + static void vsyncHook(hwc2_callback_data_t callbackData, hwc2_display_t display, + int64_t timestamp) { + auto hal = static_cast<HwcHalImpl*>(callbackData); + hal->mEventCallback->onVsync(display, timestamp); + } + + int32_t getChangedCompositionTypesInternal(Display display, uint32_t* outTypesCount, + Layer* outChangedLayers, + IComposerClient::Composition* outCompositionTypes) { + return mDispatch.getChangedCompositionTypes( + mDevice, display, outTypesCount, outChangedLayers, + reinterpret_cast<std::underlying_type<IComposerClient::Composition>::type*>( + outCompositionTypes)); + } + + hwc2_device_t* mDevice = nullptr; + + std::unordered_set<hwc2_capability_t> mCapabilities; + + struct { + HWC2_PFN_ACCEPT_DISPLAY_CHANGES acceptDisplayChanges; + HWC2_PFN_CREATE_LAYER createLayer; + HWC2_PFN_CREATE_VIRTUAL_DISPLAY createVirtualDisplay; + HWC2_PFN_DESTROY_LAYER destroyLayer; + HWC2_PFN_DESTROY_VIRTUAL_DISPLAY destroyVirtualDisplay; + HWC2_PFN_DUMP dump; + HWC2_PFN_GET_ACTIVE_CONFIG getActiveConfig; + HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES getChangedCompositionTypes; + HWC2_PFN_GET_CLIENT_TARGET_SUPPORT getClientTargetSupport; + HWC2_PFN_GET_COLOR_MODES getColorModes; + HWC2_PFN_GET_DISPLAY_ATTRIBUTE getDisplayAttribute; + HWC2_PFN_GET_DISPLAY_CONFIGS getDisplayConfigs; + HWC2_PFN_GET_DISPLAY_NAME getDisplayName; + HWC2_PFN_GET_DISPLAY_REQUESTS getDisplayRequests; + HWC2_PFN_GET_DISPLAY_TYPE getDisplayType; + HWC2_PFN_GET_DOZE_SUPPORT getDozeSupport; + HWC2_PFN_GET_HDR_CAPABILITIES getHdrCapabilities; + HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT getMaxVirtualDisplayCount; + HWC2_PFN_GET_RELEASE_FENCES getReleaseFences; + HWC2_PFN_PRESENT_DISPLAY presentDisplay; + HWC2_PFN_REGISTER_CALLBACK registerCallback; + HWC2_PFN_SET_ACTIVE_CONFIG setActiveConfig; + HWC2_PFN_SET_CLIENT_TARGET setClientTarget; + HWC2_PFN_SET_COLOR_MODE setColorMode; + HWC2_PFN_SET_COLOR_TRANSFORM setColorTransform; + HWC2_PFN_SET_CURSOR_POSITION setCursorPosition; + HWC2_PFN_SET_LAYER_BLEND_MODE setLayerBlendMode; + HWC2_PFN_SET_LAYER_BUFFER setLayerBuffer; + HWC2_PFN_SET_LAYER_COLOR setLayerColor; + HWC2_PFN_SET_LAYER_COMPOSITION_TYPE setLayerCompositionType; + HWC2_PFN_SET_LAYER_DATASPACE setLayerDataspace; + HWC2_PFN_SET_LAYER_DISPLAY_FRAME setLayerDisplayFrame; + HWC2_PFN_SET_LAYER_PLANE_ALPHA setLayerPlaneAlpha; + HWC2_PFN_SET_LAYER_SIDEBAND_STREAM setLayerSidebandStream; + HWC2_PFN_SET_LAYER_SOURCE_CROP setLayerSourceCrop; + HWC2_PFN_SET_LAYER_SURFACE_DAMAGE setLayerSurfaceDamage; + HWC2_PFN_SET_LAYER_TRANSFORM setLayerTransform; + HWC2_PFN_SET_LAYER_VISIBLE_REGION setLayerVisibleRegion; + HWC2_PFN_SET_LAYER_Z_ORDER setLayerZOrder; + HWC2_PFN_SET_OUTPUT_BUFFER setOutputBuffer; + HWC2_PFN_SET_POWER_MODE setPowerMode; + HWC2_PFN_SET_VSYNC_ENABLED setVsyncEnabled; + HWC2_PFN_VALIDATE_DISPLAY validateDisplay; + } mDispatch = {}; + + hal::ComposerHal::EventCallback* mEventCallback = nullptr; +}; + +} // namespace detail + +using HwcHal = detail::HwcHalImpl<hal::ComposerHal>; + +} // namespace passthrough +} // namespace V2_1 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/service/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h b/service/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h new file mode 100644 index 0000000..33c914d --- a/dev/null +++ b/service/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h @@ -0,0 +1,152 @@ +/* + * Copyright 2016 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. + */ + +#pragma once + +#ifndef LOG_TAG +#warning "HwcLoader.h included without LOG_TAG" +#endif + +#include <memory> + +#include <composer-hal/2.1/Composer.h> +#include <composer-passthrough/2.1/HwcHal.h> +#include <hardware/fb.h> +#include <hardware/gralloc.h> +#include <hardware/hardware.h> +#include <hardware/hwcomposer.h> +#include <hardware/hwcomposer2.h> +#include <hwc2on1adapter/HWC2On1Adapter.h> +#include <hwc2onfbadapter/HWC2OnFbAdapter.h> +#include <log/log.h> + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_1 { +namespace passthrough { + +class HwcLoader { + public: + static IComposer* load() { + const hw_module_t* module = loadModule(); + if (!module) { + return nullptr; + } + + auto hal = createHalWithAdapter(module); + if (!hal) { + return nullptr; + } + + return createComposer(std::move(hal)); + } + + // load hwcomposer2 module + static const hw_module_t* loadModule() { + const hw_module_t* module; + int error = hw_get_module(HWC_HARDWARE_MODULE_ID, &module); + if (error) { + ALOGI("falling back to gralloc module"); + error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); + } + + if (error) { + ALOGE("failed to get hwcomposer or gralloc module"); + return nullptr; + } + + return module; + } + + // create a ComposerHal instance + static std::unique_ptr<hal::ComposerHal> createHal(const hw_module_t* module) { + auto hal = std::make_unique<HwcHal>(); + return hal->initWithModule(module) ? std::move(hal) : nullptr; + } + + // create a ComposerHal instance, insert an adapter if necessary + static std::unique_ptr<hal::ComposerHal> createHalWithAdapter(const hw_module_t* module) { + bool adapted; + hwc2_device_t* device = openDeviceWithAdapter(module, &adapted); + if (!device) { + return nullptr; + } + auto hal = std::make_unique<HwcHal>(); + return hal->initWithDevice(std::move(device), !adapted) ? std::move(hal) : nullptr; + } + + // create an IComposer instance + static IComposer* createComposer(std::unique_ptr<hal::ComposerHal> hal) { + return hal::Composer::create(std::move(hal)).release(); + } + + protected: + // open hwcomposer2 device, install an adapter if necessary + static hwc2_device_t* openDeviceWithAdapter(const hw_module_t* module, bool* outAdapted) { + if (module->id && std::string(module->id) == GRALLOC_HARDWARE_MODULE_ID) { + *outAdapted = true; + return adaptGrallocModule(module); + } + + hw_device_t* device; + int error = module->methods->open(module, HWC_HARDWARE_COMPOSER, &device); + if (error) { + ALOGE("failed to open hwcomposer device: %s", strerror(-error)); + return nullptr; + } + + int major = (device->version >> 24) & 0xf; + if (major != 2) { + *outAdapted = true; + return adaptHwc1Device(std::move(reinterpret_cast<hwc_composer_device_1*>(device))); + } + + *outAdapted = false; + return reinterpret_cast<hwc2_device_t*>(device); + } + + private: + static hwc2_device_t* adaptGrallocModule(const hw_module_t* module) { + framebuffer_device_t* device; + int error = framebuffer_open(module, &device); + if (error) { + ALOGE("failed to open framebuffer device: %s", strerror(-error)); + return nullptr; + } + + return new HWC2OnFbAdapter(device); + } + + static hwc2_device_t* adaptHwc1Device(hwc_composer_device_1* device) { + int minor = (device->common.version >> 16) & 0xf; + if (minor < 1) { + ALOGE("hwcomposer 1.0 is not supported"); + device->common.close(&device->common); + return nullptr; + } + + return new HWC2On1Adapter(device); + } +}; + +} // namespace passthrough +} // namespace V2_1 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/service/2.2/utils/passthrough/Android.bp b/service/2.2/utils/passthrough/Android.bp new file mode 100644 index 0000000..318ce91 --- a/dev/null +++ b/service/2.2/utils/passthrough/Android.bp @@ -0,0 +1,14 @@ +cc_library_headers { + name: "android.hardware.graphics.composer@2.2-passthrough", + defaults: ["hidl_defaults"], + vendor: true, + header_libs: [ + "android.hardware.graphics.composer@2.1-passthrough", + "android.hardware.graphics.composer@2.2-hal", + ], + export_header_lib_headers: [ + "android.hardware.graphics.composer@2.1-passthrough", + "android.hardware.graphics.composer@2.2-hal", + ], + export_include_dirs: ["include"], +} diff --git a/service/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h b/service/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h new file mode 100644 index 0000000..93da0a5 --- a/dev/null +++ b/service/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h @@ -0,0 +1,301 @@ +/* + * Copyright 2018 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. + */ + +#pragma once + +#ifndef LOG_TAG +#warning "HwcHal.h included without LOG_TAG" +#endif + +#include <type_traits> + +#include <composer-hal/2.2/ComposerHal.h> +#include <composer-passthrough/2.1/HwcHal.h> + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_2 { +namespace passthrough { + +namespace detail { + +using common::V1_1::ColorMode; +using common::V1_1::Dataspace; +using common::V1_1::PixelFormat; +using common::V1_1::RenderIntent; +using V2_1::Display; +using V2_1::Error; +using V2_1::Layer; + +// HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2 +template <typename Hal> +class HwcHalImpl : public V2_1::passthrough::detail::HwcHalImpl<Hal> { + public: + // XXX when can we return Error::UNSUPPORTED? + + Error getPerFrameMetadataKeys( + Display display, std::vector<IComposerClient::PerFrameMetadataKey>* outKeys) override { + if (!mDispatch.getPerFrameMetadataKeys) { + return Error::UNSUPPORTED; + } + + uint32_t count = 0; + int32_t error = mDispatch.getPerFrameMetadataKeys(mDevice, display, &count, nullptr); + if (error != HWC2_ERROR_NONE) { + return static_cast<Error>(error); + } + + std::vector<IComposerClient::PerFrameMetadataKey> keys(count); + error = mDispatch.getPerFrameMetadataKeys( + mDevice, display, &count, + reinterpret_cast<std::underlying_type<IComposerClient::PerFrameMetadataKey>::type*>( + keys.data())); + if (error != HWC2_ERROR_NONE) { + return static_cast<Error>(error); + } + + keys.resize(count); + *outKeys = std::move(keys); + return Error::NONE; + } + + Error setLayerPerFrameMetadata( + Display display, Layer layer, + const std::vector<IComposerClient::PerFrameMetadata>& metadata) override { + if (!mDispatch.setLayerPerFrameMetadata) { + return Error::UNSUPPORTED; + } + + std::vector<int32_t> keys; + std::vector<float> values; + keys.reserve(metadata.size()); + values.reserve(metadata.size()); + for (const auto& m : metadata) { + keys.push_back(static_cast<int32_t>(m.key)); + values.push_back(m.value); + } + + int32_t error = mDispatch.setLayerPerFrameMetadata(mDevice, display, layer, metadata.size(), + keys.data(), values.data()); + return static_cast<Error>(error); + } + + Error getReadbackBufferAttributes(Display display, PixelFormat* outFormat, + Dataspace* outDataspace) override { + if (!mDispatch.getReadbackBufferAttributes) { + return Error::UNSUPPORTED; + } + + int32_t format = 0; + int32_t dataspace = 0; + int32_t error = + mDispatch.getReadbackBufferAttributes(mDevice, display, &format, &dataspace); + if (error == HWC2_ERROR_NONE) { + *outFormat = static_cast<PixelFormat>(format); + *outDataspace = static_cast<Dataspace>(dataspace); + } + return static_cast<Error>(error); + } + + Error setReadbackBuffer(Display display, const native_handle_t* bufferHandle, + base::unique_fd fenceFd) override { + if (!mDispatch.setReadbackBuffer) { + return Error::UNSUPPORTED; + } + + int32_t error = + mDispatch.setReadbackBuffer(mDevice, display, bufferHandle, fenceFd.release()); + return static_cast<Error>(error); + } + + Error getReadbackBufferFence(Display display, base::unique_fd* outFenceFd) override { + if (!mDispatch.getReadbackBufferFence) { + return Error::UNSUPPORTED; + } + + int32_t fenceFd = -1; + int32_t error = mDispatch.getReadbackBufferFence(mDevice, display, &fenceFd); + outFenceFd->reset(fenceFd); + return static_cast<Error>(error); + } + + Error createVirtualDisplay_2_2(uint32_t width, uint32_t height, PixelFormat* format, + Display* outDisplay) override { + return createVirtualDisplay( + width, height, reinterpret_cast<common::V1_0::PixelFormat*>(format), outDisplay); + } + + Error getClientTargetSupport_2_2(Display display, uint32_t width, uint32_t height, + PixelFormat format, Dataspace dataspace) override { + return getClientTargetSupport(display, width, height, + static_cast<common::V1_0::PixelFormat>(format), + static_cast<common::V1_0::Dataspace>(dataspace)); + } + + Error setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) override { + if (mode == IComposerClient::PowerMode::ON_SUSPEND) { + return Error::UNSUPPORTED; + } + return setPowerMode(display, static_cast<V2_1::IComposerClient::PowerMode>(mode)); + } + + Error setLayerFloatColor(Display display, Layer layer, + IComposerClient::FloatColor color) override { + if (!mDispatch.setLayerFloatColor) { + return Error::UNSUPPORTED; + } + + int32_t error = mDispatch.setLayerFloatColor( + mDevice, display, layer, hwc_float_color{color.r, color.g, color.b, color.a}); + return static_cast<Error>(error); + } + + Error getColorModes_2_2(Display display, hidl_vec<ColorMode>* outModes) override { + return getColorModes(display, + reinterpret_cast<hidl_vec<common::V1_0::ColorMode>*>(outModes)); + } + + Error getRenderIntents(Display display, ColorMode mode, + std::vector<RenderIntent>* outIntents) override { + if (!mDispatch.getRenderIntents) { + *outIntents = std::vector<RenderIntent>({RenderIntent::COLORIMETRIC}); + return Error::NONE; + } + + uint32_t count = 0; + int32_t error = + mDispatch.getRenderIntents(mDevice, display, int32_t(mode), &count, nullptr); + if (error != HWC2_ERROR_NONE) { + return static_cast<Error>(error); + } + + std::vector<RenderIntent> intents(count); + error = mDispatch.getRenderIntents( + mDevice, display, int32_t(mode), &count, + reinterpret_cast<std::underlying_type<RenderIntent>::type*>(intents.data())); + if (error != HWC2_ERROR_NONE) { + return static_cast<Error>(error); + } + intents.resize(count); + + *outIntents = std::move(intents); + return Error::NONE; + } + + Error setColorMode_2_2(Display display, ColorMode mode, RenderIntent intent) override { + if (!mDispatch.setColorModeWithRenderIntent) { + if (intent != RenderIntent::COLORIMETRIC) { + return Error::UNSUPPORTED; + } + return setColorMode(display, static_cast<common::V1_0::ColorMode>(mode)); + } + + int32_t err = mDispatch.setColorModeWithRenderIntent( + mDevice, display, static_cast<int32_t>(mode), static_cast<int32_t>(intent)); + return static_cast<Error>(err); + } + + std::array<float, 16> getDataspaceSaturationMatrix(Dataspace dataspace) override { + std::array<float, 16> matrix; + + int32_t error = HWC2_ERROR_UNSUPPORTED; + if (mDispatch.getDataspaceSaturationMatrix) { + error = mDispatch.getDataspaceSaturationMatrix(mDevice, static_cast<int32_t>(dataspace), + matrix.data()); + } + if (error != HWC2_ERROR_NONE) { + return std::array<float, 16>{ + 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, + }; + } + + return matrix; + } + + protected: + template <typename T> + bool initOptionalDispatch(hwc2_function_descriptor_t desc, T* outPfn) { + auto pfn = mDevice->getFunction(mDevice, desc); + if (pfn) { + *outPfn = reinterpret_cast<T>(pfn); + return true; + } else { + return false; + } + } + + bool initDispatch() override { + if (!BaseType2_1::initDispatch()) { + return false; + } + + initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_FLOAT_COLOR, &mDispatch.setLayerFloatColor); + + initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_PER_FRAME_METADATA, + &mDispatch.setLayerPerFrameMetadata); + initOptionalDispatch(HWC2_FUNCTION_GET_PER_FRAME_METADATA_KEYS, + &mDispatch.getPerFrameMetadataKeys); + + initOptionalDispatch(HWC2_FUNCTION_SET_READBACK_BUFFER, &mDispatch.setReadbackBuffer); + initOptionalDispatch(HWC2_FUNCTION_GET_READBACK_BUFFER_ATTRIBUTES, + &mDispatch.getReadbackBufferAttributes); + initOptionalDispatch(HWC2_FUNCTION_GET_READBACK_BUFFER_FENCE, + &mDispatch.getReadbackBufferFence); + + initOptionalDispatch(HWC2_FUNCTION_GET_RENDER_INTENTS, &mDispatch.getRenderIntents); + initOptionalDispatch(HWC2_FUNCTION_SET_COLOR_MODE_WITH_RENDER_INTENT, + &mDispatch.setColorModeWithRenderIntent); + initOptionalDispatch(HWC2_FUNCTION_GET_DATASPACE_SATURATION_MATRIX, + &mDispatch.getDataspaceSaturationMatrix); + + return true; + } + + struct { + HWC2_PFN_SET_LAYER_FLOAT_COLOR setLayerFloatColor; + HWC2_PFN_SET_LAYER_PER_FRAME_METADATA setLayerPerFrameMetadata; + HWC2_PFN_GET_PER_FRAME_METADATA_KEYS getPerFrameMetadataKeys; + HWC2_PFN_SET_READBACK_BUFFER setReadbackBuffer; + HWC2_PFN_GET_READBACK_BUFFER_ATTRIBUTES getReadbackBufferAttributes; + HWC2_PFN_GET_READBACK_BUFFER_FENCE getReadbackBufferFence; + HWC2_PFN_GET_RENDER_INTENTS getRenderIntents; + HWC2_PFN_SET_COLOR_MODE_WITH_RENDER_INTENT setColorModeWithRenderIntent; + HWC2_PFN_GET_DATASPACE_SATURATION_MATRIX getDataspaceSaturationMatrix; + } mDispatch = {}; + + private: + using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl<Hal>; + using BaseType2_1::getColorModes; + using BaseType2_1::mDevice; + using BaseType2_1::setColorMode; + using BaseType2_1::createVirtualDisplay; + using BaseType2_1::getClientTargetSupport; + using BaseType2_1::setPowerMode; +}; + +} // namespace detail + +using HwcHal = detail::HwcHalImpl<hal::ComposerHal>; + +} // namespace passthrough +} // namespace V2_2 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/service/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h b/service/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h new file mode 100644 index 0000000..cb4a238 --- a/dev/null +++ b/service/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h @@ -0,0 +1,79 @@ +/* + * Copyright 2018 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. + */ + +#pragma once + +#ifndef LOG_TAG +#warning "HwcLoader.h included without LOG_TAG" +#endif + +#include <composer-hal/2.2/Composer.h> +#include <composer-hal/2.2/ComposerHal.h> +#include <composer-passthrough/2.1/HwcLoader.h> +#include <composer-passthrough/2.2/HwcHal.h> + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_2 { +namespace passthrough { + +class HwcLoader : public V2_1::passthrough::HwcLoader { + public: + static IComposer* load() { + const hw_module_t* module = loadModule(); + if (!module) { + return nullptr; + } + + auto hal = createHalWithAdapter(module); + if (!hal) { + return nullptr; + } + + return createComposer(std::move(hal)).release(); + } + + // create a ComposerHal instance + static std::unique_ptr<hal::ComposerHal> createHal(const hw_module_t* module) { + auto hal = std::make_unique<HwcHal>(); + return hal->initWithModule(module) ? std::move(hal) : nullptr; + } + + // create a ComposerHal instance, insert an adapter if necessary + static std::unique_ptr<hal::ComposerHal> createHalWithAdapter(const hw_module_t* module) { + bool adapted; + hwc2_device_t* device = openDeviceWithAdapter(module, &adapted); + if (!device) { + return nullptr; + } + auto hal = std::make_unique<HwcHal>(); + return hal->initWithDevice(std::move(device), !adapted) ? std::move(hal) : nullptr; + } + + // create an IComposer instance + static std::unique_ptr<IComposer> createComposer(std::unique_ptr<hal::ComposerHal> hal) { + return hal::Composer::create(std::move(hal)); + } +}; + +} // namespace passthrough +} // namespace V2_2 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/service/2.3/default/Android.bp b/service/2.3/default/Android.bp new file mode 100644 index 0000000..07afd6c --- a/dev/null +++ b/service/2.3/default/Android.bp @@ -0,0 +1,46 @@ +// +// Copyright (C) 2018 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. +// + +cc_binary { + name: "android.hardware.graphics.composer@2.3-service", + defaults: ["hidl_defaults"], + vendor: true, + relative_install_path: "hw", + srcs: ["service.cpp"], + init_rc: ["android.hardware.graphics.composer@2.3-service.rc"], + header_libs: [ + "android.hardware.graphics.composer@2.3-passthrough", + ], + shared_libs: [ + "android.hardware.graphics.composer@2.1", + "android.hardware.graphics.composer@2.2", + "android.hardware.graphics.composer@2.3", + "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@3.0", + "libbase", + "libbinder", + "libcutils", + "libfmq", + "libhardware", + "libhidlbase", + "libhidltransport", + "libhwc2on1adapter", + "libhwc2onfbadapter", + "liblog", + "libsync", + "libutils", + ], +} diff --git a/service/2.3/default/android.hardware.graphics.composer@2.3-service.rc b/service/2.3/default/android.hardware.graphics.composer@2.3-service.rc new file mode 100644 index 0000000..81ce890 --- a/dev/null +++ b/service/2.3/default/android.hardware.graphics.composer@2.3-service.rc @@ -0,0 +1,7 @@ +service vendor.hwcomposer-2-3 /vendor/bin/hw/android.hardware.graphics.composer@2.3-service + class hal animation + user system + group graphics drmrpc + capabilities SYS_NICE + onrestart restart surfaceflinger + writepid /dev/cpuset/system-background/tasks diff --git a/service/2.3/default/service.cpp b/service/2.3/default/service.cpp new file mode 100644 index 0000000..347d8be --- a/dev/null +++ b/service/2.3/default/service.cpp @@ -0,0 +1,55 @@ +/* + * Copyright 2018 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 <sched.h> + +#include <android/hardware/graphics/composer/2.3/IComposer.h> +#include <binder/ProcessState.h> +#include <composer-passthrough/2.3/HwcLoader.h> +#include <hidl/HidlTransportSupport.h> + +using android::hardware::graphics::composer::V2_3::IComposer; +using android::hardware::graphics::composer::V2_3::passthrough::HwcLoader; + +int main() { + // the conventional HAL might start binder services + android::ProcessState::initWithDriver("/dev/vndbinder"); + android::ProcessState::self()->setThreadPoolMaxThreadCount(4); + android::ProcessState::self()->startThreadPool(); + + // same as SF main thread + struct sched_param param = {0}; + param.sched_priority = 2; + if (sched_setscheduler(0, SCHED_FIFO | SCHED_RESET_ON_FORK, ¶m) != 0) { + ALOGE("Couldn't set SCHED_FIFO: %d", errno); + } + + android::hardware::configureRpcThreadpool(4, true /* will join */); + + android::sp<IComposer> composer = HwcLoader::load(); + if (composer == nullptr) { + return 1; + } + if (composer->registerAsService() != android::NO_ERROR) { + ALOGE("failed to register service"); + return 1; + } + + android::hardware::joinRpcThreadpool(); + + ALOGE("service is terminating"); + return 1; +} diff --git a/service/2.3/utils/passthrough/Android.bp b/service/2.3/utils/passthrough/Android.bp new file mode 100644 index 0000000..3ae6b16 --- a/dev/null +++ b/service/2.3/utils/passthrough/Android.bp @@ -0,0 +1,30 @@ +// +// Copyright (C) 2018 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. +// + +cc_library_headers { + name: "android.hardware.graphics.composer@2.3-passthrough", + defaults: ["hidl_defaults"], + vendor: true, + header_libs: [ + "android.hardware.graphics.composer@2.2-passthrough", + "android.hardware.graphics.composer@2.3-hal", + ], + export_header_lib_headers: [ + "android.hardware.graphics.composer@2.2-passthrough", + "android.hardware.graphics.composer@2.3-hal", + ], + export_include_dirs: ["include"], +} diff --git a/service/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/service/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h new file mode 100644 index 0000000..d3b29bb --- a/dev/null +++ b/service/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h @@ -0,0 +1,441 @@ +/* + * Copyright 2018 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. + */ + +#pragma once + +#ifndef LOG_TAG +#warning "HwcHal.h included without LOG_TAG" +#endif + +#include <type_traits> + +#include <composer-hal/2.3/ComposerHal.h> +#include <composer-passthrough/2.2/HwcHal.h> + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_3 { +namespace passthrough { + +namespace detail { + +using common::V1_1::RenderIntent; +using common::V1_2::ColorMode; +using common::V1_2::Dataspace; +using common::V1_2::Hdr; +using common::V1_2::PixelFormat; +using V2_1::Display; +using V2_1::Error; + +namespace { + +bool isIdentityMatrix(const float* matrix) { + if (matrix[0] == 1.0 && matrix[1] == 0.0 && matrix[2] == 0.0 && matrix[3] == 0.0 && + matrix[4] == 0.0 && matrix[5] == 1.0 && matrix[6] == 0.0 && matrix[7] == 0.0 && + matrix[8] == 0.0 && matrix[9] == 0.0 && matrix[10] == 1.0 && matrix[11] == 0.0 && + matrix[12] == 0.0 && matrix[13] == 0.0 && matrix[14] == 0.0 && matrix[15] == 1.0) { + return true; + } + return false; +} + +} // namespace + +// HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2 +template <typename Hal> +class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl<Hal> { + public: + Error getPerFrameMetadataKeys_2_3( + Display display, std::vector<IComposerClient::PerFrameMetadataKey>* outKeys) override { + std::vector<V2_2::IComposerClient::PerFrameMetadataKey> castKeys; + Error error = getPerFrameMetadataKeys(display, &castKeys); + if (error != Error::NONE) { + return error; + } + outKeys->clear(); + for (auto key : castKeys) { + outKeys->push_back(static_cast<IComposerClient::PerFrameMetadataKey>(key)); + } + return Error::NONE; + } + + Error setLayerPerFrameMetadata_2_3( + Display display, Layer layer, + const std::vector<IComposerClient::PerFrameMetadata>& metadata) override { + return setLayerPerFrameMetadata( + display, layer, + reinterpret_cast<const std::vector<V2_2::IComposerClient::PerFrameMetadata>&>( + metadata)); + } + + Error setColorMode_2_3(Display display, ColorMode mode, RenderIntent intent) override { + return setColorMode_2_2(display, static_cast<common::V1_1::ColorMode>(mode), intent); + } + + Error getRenderIntents_2_3(Display display, ColorMode mode, + std::vector<RenderIntent>* outIntents) override { + return getRenderIntents(display, static_cast<common::V1_1::ColorMode>(mode), outIntents); + } + + Error getColorModes_2_3(Display display, hidl_vec<ColorMode>* outModes) override { + return getColorModes_2_2(display, + reinterpret_cast<hidl_vec<common::V1_1::ColorMode>*>(outModes)); + } + + Error getHdrCapabilities_2_3(Display display, hidl_vec<Hdr>* outTypes, float* outMaxLuminance, + float* outMaxAverageLuminance, float* outMinLuminance) override { + return getHdrCapabilities(display, reinterpret_cast<hidl_vec<common::V1_0::Hdr>*>(outTypes), + outMaxLuminance, outMaxAverageLuminance, outMinLuminance); + } + + Error getClientTargetSupport_2_3(Display display, uint32_t width, uint32_t height, + PixelFormat format, Dataspace dataspace) override { + return getClientTargetSupport_2_2(display, width, height, + static_cast<common::V1_1::PixelFormat>(format), + static_cast<common::V1_1::Dataspace>(dataspace)); + } + + Error getReadbackBufferAttributes_2_3(Display display, PixelFormat* outFormat, + Dataspace* outDataspace) override { + return getReadbackBufferAttributes( + display, reinterpret_cast<common::V1_1::PixelFormat*>(outFormat), + reinterpret_cast<common::V1_1::Dataspace*>(outDataspace)); + } + + Error getDisplayIdentificationData(Display display, uint8_t* outPort, + std::vector<uint8_t>* outData) override { + if (!mDispatch.getDisplayIdentificationData) { + return Error::UNSUPPORTED; + } + + uint32_t size = 0; + int32_t error = + mDispatch.getDisplayIdentificationData(mDevice, display, outPort, &size, nullptr); + if (error != HWC2_ERROR_NONE) { + return static_cast<Error>(error); + } + + std::vector<uint8_t> data(size); + error = + mDispatch.getDisplayIdentificationData(mDevice, display, outPort, &size, data.data()); + if (error != HWC2_ERROR_NONE) { + return static_cast<Error>(error); + } + + data.resize(size); + *outData = std::move(data); + return Error::NONE; + } + + Error setLayerColorTransform(Display display, Layer layer, const float* matrix) override { + if (!mDispatch.setLayerColorTransform) { + if (isIdentityMatrix(matrix)) { + // If an identity matrix is set, then we can remove the layer from client + // composition list. + mClientCompositionLayers[display].erase(layer); + return Error::UNSUPPORTED; + } + // if setLayerColorTransform is not implemented, per spec we want to make sure the + // layer marked as client composition, and thus we maintain a list, and mark all these + // layers as client composition later before validate the display. + mClientCompositionLayers[display].insert(layer); + return Error::UNSUPPORTED; + } + int32_t err = mDispatch.setLayerColorTransform(mDevice, display, layer, matrix); + return static_cast<Error>(err); + } + + Error getDisplayedContentSamplingAttributes( + uint64_t display, PixelFormat& format, Dataspace& dataspace, + hidl_bitfield<IComposerClient::FormatColorComponent>& componentMask) override { + if (!mDispatch.getDisplayedContentSamplingAttributes) { + return Error::UNSUPPORTED; + } + int32_t formatRaw = 0; + int32_t dataspaceRaw = 0; + uint8_t componentMaskRaw = 0; + int32_t errorRaw = mDispatch.getDisplayedContentSamplingAttributes( + mDevice, display, &formatRaw, &dataspaceRaw, &componentMaskRaw); + auto error = static_cast<Error>(errorRaw); + if (error == Error::NONE) { + format = static_cast<PixelFormat>(formatRaw); + dataspace = static_cast<Dataspace>(dataspaceRaw); + componentMask = + static_cast<hidl_bitfield<IComposerClient::FormatColorComponent>>(componentMaskRaw); + } + return error; + }; + + Error setDisplayedContentSamplingEnabled( + uint64_t display, IComposerClient::DisplayedContentSampling enable, + hidl_bitfield<IComposerClient::FormatColorComponent> componentMask, + uint64_t maxFrames) override { + if (!mDispatch.setDisplayedContentSamplingEnabled) { + return Error::UNSUPPORTED; + } + return static_cast<Error>(mDispatch.setDisplayedContentSamplingEnabled( + mDevice, display, static_cast<int32_t>(enable), componentMask, maxFrames)); + } + + Error getDisplayedContentSample(uint64_t display, uint64_t maxFrames, uint64_t timestamp, + uint64_t& frameCount, hidl_vec<uint64_t>& sampleComponent0, + hidl_vec<uint64_t>& sampleComponent1, + hidl_vec<uint64_t>& sampleComponent2, + hidl_vec<uint64_t>& sampleComponent3) override { + if (!mDispatch.getDisplayedContentSample) { + return Error::UNSUPPORTED; + } + + int32_t size[4] = {0}; + auto errorRaw = mDispatch.getDisplayedContentSample(mDevice, display, maxFrames, timestamp, + &frameCount, size, nullptr); + if (errorRaw != HWC2_ERROR_NONE) { + return static_cast<Error>(errorRaw); + } + + sampleComponent0.resize(size[0]); + sampleComponent1.resize(size[1]); + sampleComponent2.resize(size[2]); + sampleComponent3.resize(size[3]); + uint64_t* samples[] = {sampleComponent0.data(), sampleComponent1.data(), + sampleComponent2.data(), sampleComponent3.data()}; + errorRaw = mDispatch.getDisplayedContentSample(mDevice, display, maxFrames, timestamp, + &frameCount, size, samples); + return static_cast<Error>(errorRaw); + } + + Error getDisplayCapabilities( + Display display, + std::vector<IComposerClient::DisplayCapability>* outCapabilities) override { + uint32_t count = 0; + int32_t error = mDispatch.getDisplayCapabilities(mDevice, display, &count, nullptr); + if (error != HWC2_ERROR_NONE) { + return static_cast<Error>(error); + } + outCapabilities->resize(count); + error = mDispatch.getDisplayCapabilities( + mDevice, display, &count, + reinterpret_cast<std::underlying_type<IComposerClient::DisplayCapability>::type*>( + outCapabilities->data())); + if (error != HWC2_ERROR_NONE) { + *outCapabilities = std::vector<IComposerClient::DisplayCapability>(); + return static_cast<Error>(error); + } + return Error::NONE; + } + + Error setLayerPerFrameMetadataBlobs( + Display display, Layer layer, + std::vector<IComposerClient::PerFrameMetadataBlob>& metadata) override { + if (!mDispatch.setLayerPerFrameMetadataBlobs) { + return Error::UNSUPPORTED; + } + + std::vector<IComposerClient::PerFrameMetadataKey> keys; + std::vector<uint32_t> sizes; + std::vector<uint8_t> blobs; + + for (auto metadataBlob : metadata) { + keys.push_back(metadataBlob.key); + sizes.push_back(metadataBlob.blob.size()); + + int writeIndex = blobs.size(); + blobs.resize(blobs.size() + metadataBlob.blob.size()); + memcpy(blobs.data() + writeIndex, metadataBlob.blob.data(), metadataBlob.blob.size()); + } + + int32_t err = mDispatch.setLayerPerFrameMetadataBlobs( + mDevice, display, layer, static_cast<uint32_t>(metadata.size()), + reinterpret_cast<int32_t*>(keys.data()), reinterpret_cast<uint32_t*>(sizes.data()), + blobs.data()); + return static_cast<Error>(err); + } + + Error getDisplayBrightnessSupport(Display display, bool* outSupport) { + if (!mDispatch.getDisplayBrightnessSupport) { + // Preemptively set to false. + *outSupport = false; + // Try to query from getDisplayCapabilities. + std::vector<IComposerClient::DisplayCapability> capabilities; + Error error = getDisplayCapabilities(display, &capabilities); + if (error != Error::NONE) { + // This function is not registered, always return UNSUPPORTED. + return Error::UNSUPPORTED; + } + *outSupport = + std::find(capabilities.begin(), capabilities.end(), + IComposerClient::DisplayCapability::BRIGHTNESS) != capabilities.end(); + // This function is not registered, always return UNSUPPORTED. + return Error::UNSUPPORTED; + } + bool support = false; + int32_t error = mDispatch.getDisplayBrightnessSupport(mDevice, display, &support); + *outSupport = support; + return static_cast<Error>(error); + } + + Error setDisplayBrightness(Display display, float brightness) { + if (std::isnan(brightness) || brightness > 1.0f || + (brightness < 0.0f && brightness != -1.0f)) { + return Error::BAD_PARAMETER; + } + if (!mDispatch.setDisplayBrightness) { + return Error::UNSUPPORTED; + } + int32_t error = mDispatch.setDisplayBrightness(mDevice, display, brightness); + return static_cast<Error>(error); + } + + protected: + bool initDispatch() override { + if (!BaseType2_2::initDispatch()) { + return false; + } + + this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_IDENTIFICATION_DATA, + &mDispatch.getDisplayIdentificationData); + this->initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_COLOR_TRANSFORM, + &mDispatch.setLayerColorTransform); + this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES, + &mDispatch.getDisplayedContentSamplingAttributes); + this->initOptionalDispatch(HWC2_FUNCTION_SET_DISPLAYED_CONTENT_SAMPLING_ENABLED, + &mDispatch.setDisplayedContentSamplingEnabled); + this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAYED_CONTENT_SAMPLE, + &mDispatch.getDisplayedContentSample); + this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_CAPABILITIES, + &mDispatch.getDisplayCapabilities); + this->initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_PER_FRAME_METADATA_BLOBS, + &mDispatch.setLayerPerFrameMetadataBlobs); + this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_BRIGHTNESS_SUPPORT, + &mDispatch.getDisplayBrightnessSupport); + this->initOptionalDispatch(HWC2_FUNCTION_SET_DISPLAY_BRIGHTNESS, + &mDispatch.setDisplayBrightness); + return true; + } + + int32_t getChangedCompositionTypes(Display display, uint32_t* outTypesCount, + Layer* outChangedLayers, + IComposerClient::Composition* outCompositionTypes) override { + if (outChangedLayers == nullptr && outCompositionTypes == nullptr) { + uint32_t typesCount = 0; + int32_t error = BaseType2_1::getChangedCompositionTypesInternal(display, &typesCount, + nullptr, nullptr); + if (error != HWC2_ERROR_NONE) { + return error; + } + mChangedLayersCache[display].resize(typesCount); + mCompositionTypesCache[display].resize(typesCount); + error = BaseType2_1::getChangedCompositionTypesInternal( + display, &typesCount, mChangedLayersCache[display].data(), + mCompositionTypesCache[display].data()); + if (error != HWC2_ERROR_NONE) { + return error; + } + for (Layer layer : mClientCompositionLayers[display]) { + bool exist = false; + for (uint32_t i = 0; i < typesCount; ++i) { + if (mChangedLayersCache[display][i] == layer) { + exist = true; + break; + } + } + if (!exist) { + mChangedLayersCache[display].push_back(layer); + mCompositionTypesCache[display].push_back(IComposerClient::Composition::CLIENT); + } + } + *outTypesCount = mChangedLayersCache[display].size(); + return error; + } + for (uint32_t i = 0; i < *outTypesCount; ++i) { + if (outChangedLayers != nullptr) { + outChangedLayers[i] = mChangedLayersCache[display][i]; + } + if (outCompositionTypes != nullptr) { + outCompositionTypes[i] = mCompositionTypesCache[display][i]; + } + } + return HWC2_ERROR_NONE; + } + + void onLayerDestroyed(Display display, Layer layer) override { + if (mClientCompositionLayers.find(display) == mClientCompositionLayers.end()) { + return; + } + mClientCompositionLayers[display].erase(layer); + } + + void onBeforeValidateDisplay(Display display) override { + if (mClientCompositionLayers.find(display) == mClientCompositionLayers.end()) { + return; + } + + // clear the cache proactively so that we don't hold too much memory over time. + mChangedLayersCache[display].clear(); + mCompositionTypesCache[display].clear(); + + // SET_LAYER_COLOR_TRANSFORM is optional, and thus if it's not implemented, we need to + // follow the spec to make sure those layers marked as client composition before validate + // the display. + if (!mDispatch.setLayerColorTransform) { + for (Layer layer : mClientCompositionLayers[display]) { + BaseType2_1::setLayerCompositionType( + display, layer, static_cast<int32_t>(IComposerClient::Composition::CLIENT)); + } + } + } + + private: + struct { + HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA getDisplayIdentificationData; + HWC2_PFN_SET_LAYER_COLOR_TRANSFORM setLayerColorTransform; + HWC2_PFN_GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES getDisplayedContentSamplingAttributes; + HWC2_PFN_SET_DISPLAYED_CONTENT_SAMPLING_ENABLED setDisplayedContentSamplingEnabled; + HWC2_PFN_GET_DISPLAYED_CONTENT_SAMPLE getDisplayedContentSample; + HWC2_PFN_GET_DISPLAY_CAPABILITIES getDisplayCapabilities; + HWC2_PFN_SET_LAYER_PER_FRAME_METADATA_BLOBS setLayerPerFrameMetadataBlobs; + HWC2_PFN_GET_DISPLAY_BRIGHTNESS_SUPPORT getDisplayBrightnessSupport; + HWC2_PFN_SET_DISPLAY_BRIGHTNESS setDisplayBrightness; + } mDispatch = {}; + + using BaseType2_2 = V2_2::passthrough::detail::HwcHalImpl<Hal>; + using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl<Hal>; + using BaseType2_1::getHdrCapabilities; + using BaseType2_1::mDevice; + using BaseType2_2::getClientTargetSupport_2_2; + using BaseType2_2::getColorModes_2_2; + using BaseType2_2::getPerFrameMetadataKeys; + using BaseType2_2::getReadbackBufferAttributes; + using BaseType2_2::getRenderIntents; + using BaseType2_2::setColorMode_2_2; + using BaseType2_2::setLayerPerFrameMetadata; + std::map<Display, std::set<Layer>> mClientCompositionLayers; + std::map<Display, std::vector<Layer>> mChangedLayersCache; + std::map<Display, std::vector<IComposerClient::Composition>> mCompositionTypesCache; +}; + +} // namespace detail + +using HwcHal = detail::HwcHalImpl<hal::ComposerHal>; + +} // namespace passthrough +} // namespace V2_3 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/service/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcLoader.h b/service/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcLoader.h new file mode 100644 index 0000000..afef475 --- a/dev/null +++ b/service/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcLoader.h @@ -0,0 +1,79 @@ +/* + * Copyright 2018 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. + */ + +#pragma once + +#ifndef LOG_TAG +#warning "HwcLoader.h included without LOG_TAG" +#endif + +#include <composer-hal/2.3/Composer.h> +#include <composer-hal/2.3/ComposerHal.h> +#include <composer-passthrough/2.2/HwcLoader.h> +#include <composer-passthrough/2.3/HwcHal.h> + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_3 { +namespace passthrough { + +class HwcLoader : public V2_2::passthrough::HwcLoader { + public: + static IComposer* load() { + const hw_module_t* module = loadModule(); + if (!module) { + return nullptr; + } + + auto hal = createHalWithAdapter(module); + if (!hal) { + return nullptr; + } + + return createComposer(std::move(hal)).release(); + } + + // create a ComposerHal instance + static std::unique_ptr<hal::ComposerHal> createHal(const hw_module_t* module) { + auto hal = std::make_unique<HwcHal>(); + return hal->initWithModule(module) ? std::move(hal) : nullptr; + } + + // create a ComposerHal instance, insert an adapter if necessary + static std::unique_ptr<hal::ComposerHal> createHalWithAdapter(const hw_module_t* module) { + bool adapted; + hwc2_device_t* device = openDeviceWithAdapter(module, &adapted); + if (!device) { + return nullptr; + } + auto hal = std::make_unique<HwcHal>(); + return hal->initWithDevice(std::move(device), !adapted) ? std::move(hal) : nullptr; + } + + // create an IComposer instance + static std::unique_ptr<IComposer> createComposer(std::unique_ptr<hal::ComposerHal> hal) { + return hal::Composer::create(std::move(hal)); + } +}; + +} // namespace passthrough +} // namespace V2_3 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android |