Merge changes from topic "hwcomposer-cleanup"
* changes:
graphics: add composer 2.2 default impl
graphics: convert composer default impl to a library
graphics: add Composer to HAL support library
graphics: move ComposerClient to HAL support library
graphics: add ComposerCommandEngine
graphics: add ComposerResources
graphics: move ComposerBase to HAL support library
graphics: add libhwc2on{1,fb}adapter
graphics: more reusable libVtsHalGraphicsComposerTestUtils
graphics: clang-format composer VTS
graphics: move libVtsHalGraphicsComposerTestUtils
diff --git a/graphics/composer/2.1/default/Android.bp b/graphics/composer/2.1/default/Android.bp
index b46a1de..2de1e3c 100644
--- a/graphics/composer/2.1/default/Android.bp
+++ b/graphics/composer/2.1/default/Android.bp
@@ -1,34 +1,12 @@
-cc_library_static {
- name: "libhwcomposer-client",
- vendor_available: true,
- defaults: ["hidl_defaults"],
- export_include_dirs: ["."],
- srcs: ["ComposerClient.cpp"],
- shared_libs: [
- "android.hardware.graphics.composer@2.1",
- "android.hardware.graphics.mapper@2.0",
- "libbase",
- "libcutils",
- "libfmq",
- "libhardware",
- "libhidlbase",
- "libhidltransport",
- "liblog",
- "libsync",
- "libutils",
- ],
- header_libs: [
- "android.hardware.graphics.composer@2.1-command-buffer",
- ],
-}
-
cc_library_shared {
name: "android.hardware.graphics.composer@2.1-impl",
defaults: ["hidl_defaults"],
- proprietary: true,
+ vendor: true,
relative_install_path: "hw",
- srcs: ["Hwc.cpp"],
- static_libs: ["libhwcomposer-client"],
+ srcs: ["passthrough.cpp"],
+ header_libs: [
+ "android.hardware.graphics.composer@2.1-passthrough",
+ ],
shared_libs: [
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.mapper@2.0",
@@ -44,26 +22,21 @@
"libhwc2on1adapter",
"libhwc2onfbadapter",
],
- header_libs: [
- "android.hardware.graphics.composer@2.1-command-buffer",
+ cflags: [
+ "-DLOG_TAG=\"ComposerHal\""
],
}
cc_binary {
name: "android.hardware.graphics.composer@2.1-service",
defaults: ["hidl_defaults"],
- proprietary: true,
+ vendor: true,
relative_install_path: "hw",
srcs: ["service.cpp"],
init_rc: ["android.hardware.graphics.composer@2.1-service.rc"],
- static_libs: ["libhwcomposer-client"],
shared_libs: [
"android.hardware.graphics.composer@2.1",
- "libbase",
"libbinder",
- "libcutils",
- "libfmq",
- "libhardware",
"libhidlbase",
"libhidltransport",
"liblog",
diff --git a/graphics/composer/2.1/default/ComposerBase.h b/graphics/composer/2.1/default/ComposerBase.h
deleted file mode 100644
index e1c9d33..0000000
--- a/graphics/composer/2.1/default/ComposerBase.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_BASE_H
-#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_BASE_H
-
-#include <android/hardware/graphics/composer/2.1/IComposer.h>
-#include <hardware/hwcomposer2.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace implementation {
-
-using android::hardware::graphics::common::V1_0::PixelFormat;
-using android::hardware::graphics::common::V1_0::Transform;
-using android::hardware::graphics::common::V1_0::Dataspace;
-using android::hardware::graphics::common::V1_0::ColorMode;
-using android::hardware::graphics::common::V1_0::ColorTransform;
-using android::hardware::graphics::common::V1_0::Hdr;
-
-class ComposerBase {
-public:
- virtual ~ComposerBase() {};
-
- virtual bool hasCapability(hwc2_capability_t capability) = 0;
-
- virtual void removeClient() = 0;
- virtual void enableCallback(bool enable) = 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 implementation
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_BASE_H
diff --git a/graphics/composer/2.1/default/ComposerClient.cpp b/graphics/composer/2.1/default/ComposerClient.cpp
deleted file mode 100644
index 0fcb9de..0000000
--- a/graphics/composer/2.1/default/ComposerClient.cpp
+++ /dev/null
@@ -1,1205 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "HwcPassthrough"
-
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <log/log.h>
-
-#include "ComposerBase.h"
-#include "ComposerClient.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace implementation {
-
-namespace {
-
-using MapperError = android::hardware::graphics::mapper::V2_0::Error;
-using android::hardware::graphics::mapper::V2_0::IMapper;
-
-class HandleImporter {
-public:
- bool initialize()
- {
- // allow only one client
- if (mInitialized) {
- return false;
- }
-
- mMapper = IMapper::getService();
-
- mInitialized = true;
- return true;
- }
-
- void cleanup()
- {
- mMapper.clear();
- mInitialized = false;
- }
-
- // In IComposer, any buffer_handle_t is owned by the caller and we need to
- // make a clone for hwcomposer2. We also need to translate empty handle
- // to nullptr. This function does that, in-place.
- bool importBuffer(buffer_handle_t& handle)
- {
- if (!handle) {
- return true;
- }
-
- if (!handle->numFds && !handle->numInts) {
- handle = nullptr;
- return true;
- }
-
- MapperError error;
- buffer_handle_t importedHandle;
- mMapper->importBuffer(
- hidl_handle(handle),
- [&](const auto& tmpError, const auto& tmpBufferHandle) {
- error = tmpError;
- importedHandle = static_cast<buffer_handle_t>(tmpBufferHandle);
- });
- if (error != MapperError::NONE) {
- return false;
- }
-
- handle = importedHandle;
-
- return true;
- }
-
- void freeBuffer(buffer_handle_t handle)
- {
- if (!handle) {
- return;
- }
-
- mMapper->freeBuffer(const_cast<native_handle_t*>(handle));
- }
-
-private:
- bool mInitialized = false;
- sp<IMapper> mMapper;
-};
-
-HandleImporter sHandleImporter;
-
-} // anonymous namespace
-
-BufferCacheEntry::BufferCacheEntry()
- : mHandle(nullptr)
-{
-}
-
-BufferCacheEntry::BufferCacheEntry(BufferCacheEntry&& other)
-{
- mHandle = other.mHandle;
- other.mHandle = nullptr;
-}
-
-BufferCacheEntry& BufferCacheEntry::operator=(buffer_handle_t handle)
-{
- clear();
- mHandle = handle;
- return *this;
-}
-
-BufferCacheEntry::~BufferCacheEntry()
-{
- clear();
-}
-
-void BufferCacheEntry::clear()
-{
- if (mHandle) {
- sHandleImporter.freeBuffer(mHandle);
- }
-}
-
-ComposerClient::ComposerClient(ComposerBase& hal)
- : mHal(hal), mWriter(kWriterInitialSize)
-{
-}
-
-ComposerClient::~ComposerClient()
-{
- // 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.
- ALOGW("destroying composer client");
-
- mHal.enableCallback(false);
-
- // no need to grab the mutex as any in-flight hwbinder call would have
- // kept the client alive
- for (const auto& dpy : mDisplayData) {
- ALOGW("destroying client resources for display %" PRIu64, dpy.first);
-
- for (const auto& ly : dpy.second.Layers) {
- mHal.destroyLayer(dpy.first, ly.first);
- }
-
- if (dpy.second.IsVirtual) {
- mHal.destroyVirtualDisplay(dpy.first);
- } 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(dpy.first, &changedLayers, &compositionTypes,
- &displayRequestMask, &requestedLayers, &requestMasks);
-
- mHal.acceptDisplayChanges(dpy.first);
-
- int32_t presentFence = -1;
- std::vector<Layer> releasedLayers;
- std::vector<int32_t> releaseFences;
- mHal.presentDisplay(dpy.first, &presentFence, &releasedLayers, &releaseFences);
- if (presentFence >= 0) {
- close(presentFence);
- }
- for (auto fence : releaseFences) {
- if (fence >= 0) {
- close(fence);
- }
- }
- }
- }
-
- mDisplayData.clear();
-
- sHandleImporter.cleanup();
-
- mHal.removeClient();
-
- ALOGW("removed composer client");
-}
-
-void ComposerClient::initialize()
-{
- mReader = createCommandReader();
- if (!sHandleImporter.initialize()) {
- LOG_ALWAYS_FATAL("failed to initialize handle importer");
- }
-}
-
-void ComposerClient::onHotplug(Display display,
- IComposerCallback::Connection connected)
-{
- {
- std::lock_guard<std::mutex> lock(mDisplayDataMutex);
-
- if (connected == IComposerCallback::Connection::CONNECTED) {
- mDisplayData.emplace(display, DisplayData(false));
- } else if (connected == IComposerCallback::Connection::DISCONNECTED) {
- mDisplayData.erase(display);
- }
- }
-
- auto ret = mCallback->onHotplug(display, connected);
- ALOGE_IF(!ret.isOk(), "failed to send onHotplug: %s",
- ret.description().c_str());
-}
-
-void ComposerClient::onRefresh(Display display)
-{
- auto ret = mCallback->onRefresh(display);
- ALOGE_IF(!ret.isOk(), "failed to send onRefresh: %s",
- ret.description().c_str());
-}
-
-void ComposerClient::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());
-}
-
-Return<void> ComposerClient::registerCallback(
- const sp<IComposerCallback>& callback)
-{
- // no locking as we require this function to be called only once
- mCallback = callback;
- mHal.enableCallback(callback != nullptr);
-
- return Void();
-}
-
-Return<uint32_t> ComposerClient::getMaxVirtualDisplayCount()
-{
- return mHal.getMaxVirtualDisplayCount();
-}
-
-Return<void> ComposerClient::createVirtualDisplay(uint32_t width,
- uint32_t height, PixelFormat formatHint, uint32_t outputBufferSlotCount,
- createVirtualDisplay_cb hidl_cb)
-{
- Display display = 0;
- Error err = mHal.createVirtualDisplay(width, height,
- &formatHint, &display);
- if (err == Error::NONE) {
- std::lock_guard<std::mutex> lock(mDisplayDataMutex);
-
- auto dpy = mDisplayData.emplace(display, DisplayData(true)).first;
- dpy->second.OutputBuffers.resize(outputBufferSlotCount);
- }
-
- hidl_cb(err, display, formatHint);
- return Void();
-}
-
-Return<Error> ComposerClient::destroyVirtualDisplay(Display display)
-{
- Error err = mHal.destroyVirtualDisplay(display);
- if (err == Error::NONE) {
- std::lock_guard<std::mutex> lock(mDisplayDataMutex);
-
- mDisplayData.erase(display);
- }
-
- return err;
-}
-
-Return<void> ComposerClient::createLayer(Display display,
- uint32_t bufferSlotCount, createLayer_cb hidl_cb)
-{
- Layer layer = 0;
- Error err = mHal.createLayer(display, &layer);
- if (err == Error::NONE) {
- std::lock_guard<std::mutex> lock(mDisplayDataMutex);
- auto dpy = mDisplayData.find(display);
- // The display entry may have already been removed by onHotplug.
- if (dpy != mDisplayData.end()) {
- auto ly = dpy->second.Layers.emplace(layer, LayerBuffers()).first;
- ly->second.Buffers.resize(bufferSlotCount);
- } else {
- err = Error::BAD_DISPLAY;
- // 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.
- }
- }
-
- hidl_cb(err, layer);
- return Void();
-}
-
-Return<Error> ComposerClient::destroyLayer(Display display, Layer layer)
-{
- Error err = mHal.destroyLayer(display, layer);
- if (err == Error::NONE) {
- std::lock_guard<std::mutex> lock(mDisplayDataMutex);
-
- auto dpy = mDisplayData.find(display);
- // The display entry may have already been removed by onHotplug.
- if (dpy != mDisplayData.end()) {
- dpy->second.Layers.erase(layer);
- }
- }
-
- return err;
-}
-
-Return<void> ComposerClient::getActiveConfig(Display display,
- getActiveConfig_cb hidl_cb)
-{
- Config config = 0;
- Error err = mHal.getActiveConfig(display, &config);
-
- hidl_cb(err, config);
- return Void();
-}
-
-Return<Error> ComposerClient::getClientTargetSupport(Display display,
- uint32_t width, uint32_t height,
- PixelFormat format, Dataspace dataspace)
-{
- Error err = mHal.getClientTargetSupport(display,
- width, height, format, dataspace);
- return err;
-}
-
-Return<void> ComposerClient::getColorModes(Display display,
- getColorModes_cb hidl_cb)
-{
- hidl_vec<ColorMode> modes;
- Error err = mHal.getColorModes(display, &modes);
-
- hidl_cb(err, modes);
- return Void();
-}
-
-Return<void> ComposerClient::getDisplayAttribute(Display display,
- Config config, Attribute attribute,
- getDisplayAttribute_cb hidl_cb)
-{
- int32_t value = 0;
- Error err = mHal.getDisplayAttribute(display, config, attribute, &value);
-
- hidl_cb(err, value);
- return Void();
-}
-
-Return<void> ComposerClient::getDisplayConfigs(Display display,
- getDisplayConfigs_cb hidl_cb)
-{
- hidl_vec<Config> configs;
- Error err = mHal.getDisplayConfigs(display, &configs);
-
- hidl_cb(err, configs);
- return Void();
-}
-
-Return<void> ComposerClient::getDisplayName(Display display,
- getDisplayName_cb hidl_cb)
-{
- hidl_string name;
- Error err = mHal.getDisplayName(display, &name);
-
- hidl_cb(err, name);
- return Void();
-}
-
-Return<void> ComposerClient::getDisplayType(Display display,
- getDisplayType_cb hidl_cb)
-{
- DisplayType type = DisplayType::INVALID;
- Error err = mHal.getDisplayType(display, &type);
-
- hidl_cb(err, type);
- return Void();
-}
-
-Return<void> ComposerClient::getDozeSupport(Display display,
- getDozeSupport_cb hidl_cb)
-{
- bool support = false;
- Error err = mHal.getDozeSupport(display, &support);
-
- hidl_cb(err, support);
- return Void();
-}
-
-Return<void> ComposerClient::getHdrCapabilities(Display display,
- getHdrCapabilities_cb hidl_cb)
-{
- 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> ComposerClient::setClientTargetSlotCount(Display display,
- uint32_t clientTargetSlotCount)
-{
- std::lock_guard<std::mutex> lock(mDisplayDataMutex);
-
- auto dpy = mDisplayData.find(display);
- if (dpy == mDisplayData.end()) {
- return Error::BAD_DISPLAY;
- }
-
- dpy->second.ClientTargets.resize(clientTargetSlotCount);
-
- return Error::NONE;
-}
-
-Return<Error> ComposerClient::setActiveConfig(Display display, Config config)
-{
- Error err = mHal.setActiveConfig(display, config);
- return err;
-}
-
-Return<Error> ComposerClient::setColorMode(Display display, ColorMode mode)
-{
- Error err = mHal.setColorMode(display, mode);
- return err;
-}
-
-Return<Error> ComposerClient::setPowerMode(Display display, PowerMode mode)
-{
- Error err = mHal.setPowerMode(display, mode);
- return err;
-}
-
-Return<Error> ComposerClient::setVsyncEnabled(Display display, Vsync enabled)
-{
- Error err = mHal.setVsyncEnabled(display, enabled);
- return err;
-}
-
-Return<Error> ComposerClient::setInputCommandQueue(
- const MQDescriptorSync<uint32_t>& descriptor)
-{
- std::lock_guard<std::mutex> lock(mCommandMutex);
- return mReader->setMQDescriptor(descriptor) ?
- Error::NONE : Error::NO_RESOURCES;
-}
-
-Return<void> ComposerClient::getOutputCommandQueue(
- getOutputCommandQueue_cb hidl_cb)
-{
- // no locking as we require this function to be called inside
- // executeCommands_cb
-
- auto outDescriptor = mWriter.getMQDescriptor();
- if (outDescriptor) {
- hidl_cb(Error::NONE, *outDescriptor);
- } else {
- hidl_cb(Error::NO_RESOURCES, CommandQueueType::Descriptor());
- }
-
- return Void();
-}
-
-Return<void> ComposerClient::executeCommands(uint32_t inLength,
- const hidl_vec<hidl_handle>& inHandles,
- executeCommands_cb hidl_cb)
-{
- std::lock_guard<std::mutex> lock(mCommandMutex);
-
- bool outChanged = false;
- uint32_t outLength = 0;
- hidl_vec<hidl_handle> outHandles;
-
- if (!mReader->readQueue(inLength, inHandles)) {
- hidl_cb(Error::BAD_PARAMETER, outChanged, outLength, outHandles);
- return Void();
- }
-
- Error err = mReader->parse();
- if (err == Error::NONE &&
- !mWriter.writeQueue(&outChanged, &outLength, &outHandles)) {
- err = Error::NO_RESOURCES;
- }
-
- hidl_cb(err, outChanged, outLength, outHandles);
-
- mReader->reset();
- mWriter.reset();
-
- return Void();
-}
-
-std::unique_ptr<ComposerClient::CommandReader>
-ComposerClient::createCommandReader()
-{
- return std::unique_ptr<ComposerClient::CommandReader>(
- new CommandReader(*this));
-}
-
-ComposerClient::CommandReader::CommandReader(ComposerClient& client)
- : mClient(client), mHal(client.mHal), mWriter(client.mWriter)
-{
-}
-
-ComposerClient::CommandReader::~CommandReader()
-{
-}
-
-Error ComposerClient::CommandReader::parse()
-{
- IComposerClient::Command command;
- uint16_t length = 0;
-
- while (!isEmpty()) {
- if (!beginCommand(&command, &length)) {
- break;
- }
-
- bool parsed = parseCommand(command, length);
- endCommand();
-
- if (!parsed) {
- ALOGE("failed to parse command 0x%x, length %" PRIu16,
- command, length);
- break;
- }
- }
-
- return (isEmpty()) ? Error::NONE : Error::BAD_PARAMETER;
-}
-
-bool ComposerClient::CommandReader::parseCommand(
- IComposerClient::Command command, uint16_t length) {
- switch (command) {
- case IComposerClient::Command::SELECT_DISPLAY:
- return parseSelectDisplay(length);
- case IComposerClient::Command::SELECT_LAYER:
- return parseSelectLayer(length);
- case IComposerClient::Command::SET_COLOR_TRANSFORM:
- return parseSetColorTransform(length);
- case IComposerClient::Command::SET_CLIENT_TARGET:
- return parseSetClientTarget(length);
- case IComposerClient::Command::SET_OUTPUT_BUFFER:
- return parseSetOutputBuffer(length);
- case IComposerClient::Command::VALIDATE_DISPLAY:
- return parseValidateDisplay(length);
- case IComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY:
- return parsePresentOrValidateDisplay(length);
- case IComposerClient::Command::ACCEPT_DISPLAY_CHANGES:
- return parseAcceptDisplayChanges(length);
- case IComposerClient::Command::PRESENT_DISPLAY:
- return parsePresentDisplay(length);
- case IComposerClient::Command::SET_LAYER_CURSOR_POSITION:
- return parseSetLayerCursorPosition(length);
- case IComposerClient::Command::SET_LAYER_BUFFER:
- return parseSetLayerBuffer(length);
- case IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE:
- return parseSetLayerSurfaceDamage(length);
- case IComposerClient::Command::SET_LAYER_BLEND_MODE:
- return parseSetLayerBlendMode(length);
- case IComposerClient::Command::SET_LAYER_COLOR:
- return parseSetLayerColor(length);
- case IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE:
- return parseSetLayerCompositionType(length);
- case IComposerClient::Command::SET_LAYER_DATASPACE:
- return parseSetLayerDataspace(length);
- case IComposerClient::Command::SET_LAYER_DISPLAY_FRAME:
- return parseSetLayerDisplayFrame(length);
- case IComposerClient::Command::SET_LAYER_PLANE_ALPHA:
- return parseSetLayerPlaneAlpha(length);
- case IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM:
- return parseSetLayerSidebandStream(length);
- case IComposerClient::Command::SET_LAYER_SOURCE_CROP:
- return parseSetLayerSourceCrop(length);
- case IComposerClient::Command::SET_LAYER_TRANSFORM:
- return parseSetLayerTransform(length);
- case IComposerClient::Command::SET_LAYER_VISIBLE_REGION:
- return parseSetLayerVisibleRegion(length);
- case IComposerClient::Command::SET_LAYER_Z_ORDER:
- return parseSetLayerZOrder(length);
- default:
- return false;
- }
-}
-
-bool ComposerClient::CommandReader::parseSelectDisplay(uint16_t length)
-{
- if (length != CommandWriterBase::kSelectDisplayLength) {
- return false;
- }
-
- mDisplay = read64();
- mWriter.selectDisplay(mDisplay);
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parseSelectLayer(uint16_t length)
-{
- if (length != CommandWriterBase::kSelectLayerLength) {
- return false;
- }
-
- mLayer = read64();
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parseSetColorTransform(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(mDisplay, matrix, transform);
- if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parseSetClientTarget(uint16_t length)
-{
- // 4 parameters followed by N rectangles
- if ((length - 4) % 4 != 0) {
- return false;
- }
-
- bool useCache = false;
- auto slot = read();
- auto clientTarget = readHandle(&useCache);
- auto fence = readFence();
- auto dataspace = readSigned();
- auto damage = readRegion((length - 4) / 4);
- bool closeFence = true;
-
- auto err = lookupBuffer(BufferCache::CLIENT_TARGETS,
- slot, useCache, clientTarget, &clientTarget);
- if (err == Error::NONE) {
- err = mHal.setClientTarget(mDisplay, clientTarget, fence,
- dataspace, damage);
- auto updateBufErr = updateBuffer(BufferCache::CLIENT_TARGETS, slot,
- useCache, clientTarget);
- if (err == Error::NONE) {
- closeFence = false;
- err = updateBufErr;
- }
- }
- if (closeFence) {
- close(fence);
- }
- if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parseSetOutputBuffer(uint16_t length)
-{
- if (length != CommandWriterBase::kSetOutputBufferLength) {
- return false;
- }
-
- bool useCache = false;
- auto slot = read();
- auto outputBuffer = readHandle(&useCache);
- auto fence = readFence();
- bool closeFence = true;
-
- auto err = lookupBuffer(BufferCache::OUTPUT_BUFFERS,
- slot, useCache, outputBuffer, &outputBuffer);
- if (err == Error::NONE) {
- err = mHal.setOutputBuffer(mDisplay, outputBuffer, fence);
- auto updateBufErr = updateBuffer(BufferCache::OUTPUT_BUFFERS,
- slot, useCache, outputBuffer);
- if (err == Error::NONE) {
- closeFence = false;
- err = updateBufErr;
- }
- }
- if (closeFence) {
- close(fence);
- }
- if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parseValidateDisplay(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(mDisplay, &changedLayers,
- &compositionTypes, &displayRequestMask,
- &requestedLayers, &requestMasks);
- if (err == Error::NONE) {
- mWriter.setChangedCompositionTypes(changedLayers,
- compositionTypes);
- mWriter.setDisplayRequests(displayRequestMask,
- requestedLayers, requestMasks);
- } else {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parsePresentOrValidateDisplay(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 = mHal.presentDisplay(mDisplay, &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(mDisplay, &changedLayers, &compositionTypes,
- &displayRequestMask, &requestedLayers, &requestMasks);
- if (err == Error::NONE) {
- mWriter.setPresentOrValidateResult(0);
- mWriter.setChangedCompositionTypes(changedLayers,
- compositionTypes);
- mWriter.setDisplayRequests(displayRequestMask,
- requestedLayers, requestMasks);
- } else {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parseAcceptDisplayChanges(uint16_t length)
-{
- if (length != CommandWriterBase::kAcceptDisplayChangesLength) {
- return false;
- }
-
- auto err = mHal.acceptDisplayChanges(mDisplay);
- if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parsePresentDisplay(uint16_t length)
-{
- if (length != CommandWriterBase::kPresentDisplayLength) {
- return false;
- }
-
- int presentFence = -1;
- std::vector<Layer> layers;
- std::vector<int> fences;
- auto err = mHal.presentDisplay(mDisplay, &presentFence, &layers, &fences);
- if (err == Error::NONE) {
- mWriter.setPresentFence(presentFence);
- mWriter.setReleaseFences(layers, fences);
- } else {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerCursorPosition(uint16_t length)
-{
- if (length != CommandWriterBase::kSetLayerCursorPositionLength) {
- return false;
- }
-
- auto err = mHal.setLayerCursorPosition(mDisplay, mLayer,
- readSigned(), readSigned());
- if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerBuffer(uint16_t length)
-{
- if (length != CommandWriterBase::kSetLayerBufferLength) {
- return false;
- }
-
- bool useCache = false;
- auto slot = read();
- auto buffer = readHandle(&useCache);
- auto fence = readFence();
- bool closeFence = true;
-
- auto err = lookupBuffer(BufferCache::LAYER_BUFFERS,
- slot, useCache, buffer, &buffer);
- if (err == Error::NONE) {
- err = mHal.setLayerBuffer(mDisplay, mLayer, buffer, fence);
- auto updateBufErr = updateBuffer(BufferCache::LAYER_BUFFERS, slot,
- useCache, buffer);
- if (err == Error::NONE) {
- closeFence = false;
- err = updateBufErr;
- }
- }
- if (closeFence) {
- close(fence);
- }
- if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerSurfaceDamage(uint16_t length)
-{
- // N rectangles
- if (length % 4 != 0) {
- return false;
- }
-
- auto damage = readRegion(length / 4);
- auto err = mHal.setLayerSurfaceDamage(mDisplay, mLayer, damage);
- if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerBlendMode(uint16_t length)
-{
- if (length != CommandWriterBase::kSetLayerBlendModeLength) {
- return false;
- }
-
- auto err = mHal.setLayerBlendMode(mDisplay, mLayer, readSigned());
- if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerColor(uint16_t length)
-{
- if (length != CommandWriterBase::kSetLayerColorLength) {
- return false;
- }
-
- auto err = mHal.setLayerColor(mDisplay, mLayer, readColor());
- if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerCompositionType(
- uint16_t length)
-{
- if (length != CommandWriterBase::kSetLayerCompositionTypeLength) {
- return false;
- }
-
- auto err = mHal.setLayerCompositionType(mDisplay, mLayer, readSigned());
- if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerDataspace(uint16_t length)
-{
- if (length != CommandWriterBase::kSetLayerDataspaceLength) {
- return false;
- }
-
- auto err = mHal.setLayerDataspace(mDisplay, mLayer, readSigned());
- if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerDisplayFrame(uint16_t length)
-{
- if (length != CommandWriterBase::kSetLayerDisplayFrameLength) {
- return false;
- }
-
- auto err = mHal.setLayerDisplayFrame(mDisplay, mLayer, readRect());
- if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerPlaneAlpha(uint16_t length)
-{
- if (length != CommandWriterBase::kSetLayerPlaneAlphaLength) {
- return false;
- }
-
- auto err = mHal.setLayerPlaneAlpha(mDisplay, mLayer, readFloat());
- if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerSidebandStream(uint16_t length)
-{
- if (length != CommandWriterBase::kSetLayerSidebandStreamLength) {
- return false;
- }
-
- auto stream = readHandle();
-
- auto err = lookupLayerSidebandStream(stream, &stream);
- if (err == Error::NONE) {
- err = mHal.setLayerSidebandStream(mDisplay, mLayer, stream);
- auto updateErr = updateLayerSidebandStream(stream);
- if (err == Error::NONE) {
- err = updateErr;
- }
- }
- if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerSourceCrop(uint16_t length)
-{
- if (length != CommandWriterBase::kSetLayerSourceCropLength) {
- return false;
- }
-
- auto err = mHal.setLayerSourceCrop(mDisplay, mLayer, readFRect());
- if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerTransform(uint16_t length)
-{
- if (length != CommandWriterBase::kSetLayerTransformLength) {
- return false;
- }
-
- auto err = mHal.setLayerTransform(mDisplay, mLayer, readSigned());
- if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerVisibleRegion(uint16_t length)
-{
- // N rectangles
- if (length % 4 != 0) {
- return false;
- }
-
- auto region = readRegion(length / 4);
- auto err = mHal.setLayerVisibleRegion(mDisplay, mLayer, region);
- if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerZOrder(uint16_t length)
-{
- if (length != CommandWriterBase::kSetLayerZOrderLength) {
- return false;
- }
-
- auto err = mHal.setLayerZOrder(mDisplay, mLayer, read());
- if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
- }
-
- return true;
-}
-
-hwc_rect_t ComposerClient::CommandReader::readRect()
-{
- return hwc_rect_t{
- readSigned(),
- readSigned(),
- readSigned(),
- readSigned(),
- };
-}
-
-std::vector<hwc_rect_t> ComposerClient::CommandReader::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 ComposerClient::CommandReader::readFRect()
-{
- return hwc_frect_t{
- readFloat(),
- readFloat(),
- readFloat(),
- readFloat(),
- };
-}
-
-Error ComposerClient::CommandReader::lookupBufferCacheEntryLocked(
- BufferCache cache, uint32_t slot, BufferCacheEntry** outEntry)
-{
- auto dpy = mClient.mDisplayData.find(mDisplay);
- if (dpy == mClient.mDisplayData.end()) {
- return Error::BAD_DISPLAY;
- }
-
- BufferCacheEntry* entry = nullptr;
- switch (cache) {
- case BufferCache::CLIENT_TARGETS:
- if (slot < dpy->second.ClientTargets.size()) {
- entry = &dpy->second.ClientTargets[slot];
- }
- break;
- case BufferCache::OUTPUT_BUFFERS:
- if (slot < dpy->second.OutputBuffers.size()) {
- entry = &dpy->second.OutputBuffers[slot];
- }
- break;
- case BufferCache::LAYER_BUFFERS:
- {
- auto ly = dpy->second.Layers.find(mLayer);
- if (ly == dpy->second.Layers.end()) {
- return Error::BAD_LAYER;
- }
- if (slot < ly->second.Buffers.size()) {
- entry = &ly->second.Buffers[slot];
- }
- }
- break;
- case BufferCache::LAYER_SIDEBAND_STREAMS:
- {
- auto ly = dpy->second.Layers.find(mLayer);
- if (ly == dpy->second.Layers.end()) {
- return Error::BAD_LAYER;
- }
- if (slot == 0) {
- entry = &ly->second.SidebandStream;
- }
- }
- break;
- default:
- break;
- }
-
- if (!entry) {
- ALOGW("invalid buffer slot %" PRIu32, slot);
- return Error::BAD_PARAMETER;
- }
-
- *outEntry = entry;
-
- return Error::NONE;
-}
-
-Error ComposerClient::CommandReader::lookupBuffer(BufferCache cache,
- uint32_t slot, bool useCache, buffer_handle_t handle,
- buffer_handle_t* outHandle)
-{
- if (useCache) {
- std::lock_guard<std::mutex> lock(mClient.mDisplayDataMutex);
-
- BufferCacheEntry* entry;
- Error error = lookupBufferCacheEntryLocked(cache, slot, &entry);
- if (error != Error::NONE) {
- return error;
- }
-
- // input handle is ignored
- *outHandle = entry->getHandle();
- } else if (cache == BufferCache::LAYER_SIDEBAND_STREAMS) {
- if (handle) {
- *outHandle = native_handle_clone(handle);
- if (*outHandle == nullptr) {
- return Error::NO_RESOURCES;
- }
- }
- } else {
- if (!sHandleImporter.importBuffer(handle)) {
- return Error::NO_RESOURCES;
- }
-
- *outHandle = handle;
- }
-
- return Error::NONE;
-}
-
-Error ComposerClient::CommandReader::updateBuffer(BufferCache cache,
- uint32_t slot, bool useCache, buffer_handle_t handle)
-{
- // handle was looked up from cache
- if (useCache) {
- return Error::NONE;
- }
-
- std::lock_guard<std::mutex> lock(mClient.mDisplayDataMutex);
-
- BufferCacheEntry* entry = nullptr;
- Error error = lookupBufferCacheEntryLocked(cache, slot, &entry);
- if (error != Error::NONE) {
- return error;
- }
-
- *entry = handle;
- return Error::NONE;
-}
-
-} // namespace implementation
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/composer/2.1/default/ComposerClient.h b/graphics/composer/2.1/default/ComposerClient.h
deleted file mode 100644
index 104ed5a..0000000
--- a/graphics/composer/2.1/default/ComposerClient.h
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_CLIENT_H
-#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_CLIENT_H
-
-#include <mutex>
-#include <unordered_map>
-#include <vector>
-
-#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
-#include <hardware/hwcomposer2.h>
-#include "ComposerBase.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace implementation {
-
-class BufferCacheEntry {
-public:
- BufferCacheEntry();
- BufferCacheEntry(BufferCacheEntry&& other);
-
- BufferCacheEntry(const BufferCacheEntry& other) = delete;
- BufferCacheEntry& operator=(const BufferCacheEntry& other) = delete;
-
- BufferCacheEntry& operator=(buffer_handle_t handle);
- ~BufferCacheEntry();
-
- buffer_handle_t getHandle() const { return mHandle; }
-
-private:
- void clear();
-
- buffer_handle_t mHandle;
-};
-
-class ComposerClient : public IComposerClient {
-public:
- ComposerClient(ComposerBase& hal);
- virtual ~ComposerClient();
-
- void initialize();
-
- void onHotplug(Display display, IComposerCallback::Connection connected);
- void onRefresh(Display display);
- void onVsync(Display display, int64_t timestamp);
-
- // IComposerClient interface
- Return<void> registerCallback(
- const sp<IComposerCallback>& callback) override;
- Return<uint32_t> getMaxVirtualDisplayCount() override;
- Return<void> createVirtualDisplay(uint32_t width, uint32_t height,
- PixelFormat formatHint, uint32_t outputBufferSlotCount,
- createVirtualDisplay_cb hidl_cb) override;
- Return<Error> destroyVirtualDisplay(Display display) override;
- Return<void> createLayer(Display display, uint32_t bufferSlotCount,
- createLayer_cb hidl_cb) override;
- Return<Error> destroyLayer(Display display, Layer layer) override;
- Return<void> getActiveConfig(Display display,
- getActiveConfig_cb hidl_cb) override;
- Return<Error> getClientTargetSupport(Display display,
- uint32_t width, uint32_t height,
- PixelFormat format, Dataspace dataspace) override;
- Return<void> getColorModes(Display display,
- getColorModes_cb hidl_cb) override;
- Return<void> getDisplayAttribute(Display display,
- Config config, Attribute attribute,
- getDisplayAttribute_cb hidl_cb) override;
- Return<void> getDisplayConfigs(Display display,
- getDisplayConfigs_cb hidl_cb) override;
- Return<void> getDisplayName(Display display,
- getDisplayName_cb hidl_cb) override;
- Return<void> getDisplayType(Display display,
- getDisplayType_cb hidl_cb) override;
- Return<void> getDozeSupport(Display display,
- getDozeSupport_cb hidl_cb) override;
- Return<void> getHdrCapabilities(Display display,
- getHdrCapabilities_cb hidl_cb) override;
- Return<Error> setActiveConfig(Display display, Config config) override;
- Return<Error> setColorMode(Display display, ColorMode mode) override;
- Return<Error> setPowerMode(Display display, PowerMode mode) override;
- Return<Error> setVsyncEnabled(Display display, Vsync enabled) override;
- Return<Error> setClientTargetSlotCount(Display display,
- uint32_t clientTargetSlotCount) override;
- Return<Error> setInputCommandQueue(
- const MQDescriptorSync<uint32_t>& descriptor) override;
- Return<void> getOutputCommandQueue(
- getOutputCommandQueue_cb hidl_cb) override;
- Return<void> executeCommands(uint32_t inLength,
- const hidl_vec<hidl_handle>& inHandles,
- executeCommands_cb hidl_cb) override;
-
-protected:
- struct LayerBuffers {
- std::vector<BufferCacheEntry> Buffers;
- // the handle is a sideband stream handle, not a buffer handle
- BufferCacheEntry SidebandStream;
- };
-
- struct DisplayData {
- bool IsVirtual;
-
- std::vector<BufferCacheEntry> ClientTargets;
- std::vector<BufferCacheEntry> OutputBuffers;
-
- std::unordered_map<Layer, LayerBuffers> Layers;
-
- DisplayData(bool isVirtual) : IsVirtual(isVirtual) {}
- };
-
- class CommandReader : public CommandReaderBase {
- public:
- CommandReader(ComposerClient& client);
- virtual ~CommandReader();
-
- Error parse();
-
- protected:
- virtual bool parseCommand(IComposerClient::Command command,
- uint16_t length);
-
- bool parseSelectDisplay(uint16_t length);
- bool parseSelectLayer(uint16_t length);
- bool parseSetColorTransform(uint16_t length);
- bool parseSetClientTarget(uint16_t length);
- bool parseSetOutputBuffer(uint16_t length);
- bool parseValidateDisplay(uint16_t length);
- bool parsePresentOrValidateDisplay(uint16_t length);
- bool parseAcceptDisplayChanges(uint16_t length);
- bool parsePresentDisplay(uint16_t length);
- bool parseSetLayerCursorPosition(uint16_t length);
- bool parseSetLayerBuffer(uint16_t length);
- bool parseSetLayerSurfaceDamage(uint16_t length);
- bool parseSetLayerBlendMode(uint16_t length);
- bool parseSetLayerColor(uint16_t length);
- bool parseSetLayerCompositionType(uint16_t length);
- bool parseSetLayerDataspace(uint16_t length);
- bool parseSetLayerDisplayFrame(uint16_t length);
- bool parseSetLayerPlaneAlpha(uint16_t length);
- bool parseSetLayerSidebandStream(uint16_t length);
- bool parseSetLayerSourceCrop(uint16_t length);
- bool parseSetLayerTransform(uint16_t length);
- bool parseSetLayerVisibleRegion(uint16_t length);
- bool parseSetLayerZOrder(uint16_t length);
-
- hwc_rect_t readRect();
- std::vector<hwc_rect_t> readRegion(size_t count);
- hwc_frect_t readFRect();
-
- enum class BufferCache {
- CLIENT_TARGETS,
- OUTPUT_BUFFERS,
- LAYER_BUFFERS,
- LAYER_SIDEBAND_STREAMS,
- };
- Error lookupBufferCacheEntryLocked(BufferCache cache, uint32_t slot,
- BufferCacheEntry** outEntry);
- Error lookupBuffer(BufferCache cache, uint32_t slot,
- bool useCache, buffer_handle_t handle,
- buffer_handle_t* outHandle);
- Error updateBuffer(BufferCache cache, uint32_t slot,
- bool useCache, buffer_handle_t handle);
-
- Error lookupLayerSidebandStream(buffer_handle_t handle,
- buffer_handle_t* outHandle)
- {
- return lookupBuffer(BufferCache::LAYER_SIDEBAND_STREAMS,
- 0, false, handle, outHandle);
- }
- Error updateLayerSidebandStream(buffer_handle_t handle)
- {
- return updateBuffer(BufferCache::LAYER_SIDEBAND_STREAMS,
- 0, false, handle);
- }
-
- ComposerClient& mClient;
- ComposerBase& mHal;
- CommandWriterBase& mWriter;
-
- Display mDisplay;
- Layer mLayer;
- };
-
- virtual std::unique_ptr<CommandReader> createCommandReader();
-
- ComposerBase& mHal;
-
- // 64KiB minus a small space for metadata such as read/write pointers
- static constexpr size_t kWriterInitialSize =
- 64 * 1024 / sizeof(uint32_t) - 16;
- std::mutex mCommandMutex;
- std::unique_ptr<CommandReader> mReader;
- CommandWriterBase mWriter;
-
- sp<IComposerCallback> mCallback;
-
- std::mutex mDisplayDataMutex;
- std::unordered_map<Display, DisplayData> mDisplayData;
-};
-
-} // namespace implementation
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_CLIENT_H
diff --git a/graphics/composer/2.1/default/Hwc.cpp b/graphics/composer/2.1/default/Hwc.cpp
deleted file mode 100644
index cb393ec..0000000
--- a/graphics/composer/2.1/default/Hwc.cpp
+++ /dev/null
@@ -1,817 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "HwcPassthrough"
-
-#include "Hwc.h"
-
-#include <chrono>
-#include <type_traits>
-#include <log/log.h>
-
-#include "ComposerClient.h"
-#include "hardware/fb.h"
-#include "hardware/hwcomposer.h"
-#include "hwc2on1adapter/HWC2On1Adapter.h"
-#include "hwc2onfbadapter/HWC2OnFbAdapter.h"
-
-using namespace std::chrono_literals;
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace implementation {
-
-HwcHal::HwcHal(const hw_module_t* module)
- : mDevice(nullptr), mDispatch(), mMustValidateDisplay(true), mAdapter() {
- uint32_t majorVersion;
- if (module->id && strcmp(module->id, GRALLOC_HARDWARE_MODULE_ID) == 0) {
- majorVersion = initWithFb(module);
- } else {
- majorVersion = initWithHwc(module);
- }
-
- initCapabilities();
- if (majorVersion >= 2 && hasCapability(HWC2_CAPABILITY_PRESENT_FENCE_IS_NOT_RELIABLE)) {
- ALOGE("Present fence must be reliable from HWC2 on.");
- abort();
- }
-
- initDispatch();
-}
-
-HwcHal::~HwcHal()
-{
- hwc2_close(mDevice);
-}
-
-uint32_t HwcHal::initWithHwc(const hw_module_t* module)
-{
- // Determine what kind of module is available (HWC2 vs HWC1.X).
- hw_device_t* device = nullptr;
- int error = module->methods->open(module, HWC_HARDWARE_COMPOSER, &device);
- if (error != 0) {
- ALOGE("Failed to open HWC device (%s), aborting", strerror(-error));
- abort();
- }
- uint32_t majorVersion = (device->version >> 24) & 0xF;
-
- // If we don't have a HWC2, we need to wrap whatever we have in an adapter.
- if (majorVersion != 2) {
- uint32_t minorVersion = device->version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
- minorVersion = (minorVersion >> 16) & 0xF;
- ALOGI("Found HWC implementation v%d.%d", majorVersion, minorVersion);
- if (minorVersion < 1) {
- ALOGE("Cannot adapt to HWC version %d.%d. Minimum supported is 1.1",
- majorVersion, minorVersion);
- abort();
- }
- mAdapter = std::make_unique<HWC2On1Adapter>(
- reinterpret_cast<hwc_composer_device_1*>(device));
-
- // Place the adapter in front of the device module.
- mDevice = mAdapter.get();
- } else {
- mDevice = reinterpret_cast<hwc2_device_t*>(device);
- }
-
- return majorVersion;
-}
-
-uint32_t HwcHal::initWithFb(const hw_module_t* module)
-{
- framebuffer_device_t* fb_device;
- int error = framebuffer_open(module, &fb_device);
- if (error != 0) {
- ALOGE("Failed to open FB device (%s), aborting", strerror(-error));
- abort();
- }
-
- mFbAdapter = std::make_unique<HWC2OnFbAdapter>(fb_device);
- mDevice = mFbAdapter.get();
-
- return 0;
-}
-
-void HwcHal::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>
-void HwcHal::initDispatch(hwc2_function_descriptor_t desc, T* outPfn)
-{
- auto pfn = mDevice->getFunction(mDevice, desc);
- if (!pfn) {
- LOG_ALWAYS_FATAL("failed to get hwcomposer2 function %d", desc);
- }
-
- *outPfn = reinterpret_cast<T>(pfn);
-}
-
-void HwcHal::initDispatch()
-{
- 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);
-
- if (hasCapability(HWC2_CAPABILITY_SIDEBAND_STREAM)) {
- initDispatch(HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM,
- &mDispatch.setLayerSidebandStream);
- }
-
- 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);
-}
-
-bool HwcHal::hasCapability(hwc2_capability_t capability) {
- return (mCapabilities.count(capability) > 0);
-}
-
-Return<void> HwcHal::getCapabilities(getCapabilities_cb hidl_cb)
-{
- std::vector<Capability> caps;
- caps.reserve(mCapabilities.size());
- for (auto cap : mCapabilities) {
- switch (cap) {
- case HWC2_CAPABILITY_SIDEBAND_STREAM:
- case HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM:
- case HWC2_CAPABILITY_PRESENT_FENCE_IS_NOT_RELIABLE:
- caps.push_back(static_cast<Capability>(cap));
- break;
- default:
- // not all HWC2 caps are defined in HIDL
- break;
- }
- }
-
- hidl_vec<Capability> caps_reply;
- caps_reply.setToExternal(caps.data(), caps.size());
- hidl_cb(caps_reply);
-
- return Void();
-}
-
-Return<void> HwcHal::dumpDebugInfo(dumpDebugInfo_cb hidl_cb)
-{
- 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';
-
- hidl_string buf_reply;
- buf_reply.setToExternal(buf.data(), len);
- hidl_cb(buf_reply);
-
- return Void();
-}
-
-Return<void> HwcHal::createClient(createClient_cb hidl_cb)
-{
- Error err = Error::NONE;
- sp<ComposerClient> client;
-
- {
- std::unique_lock<std::mutex> lock(mClientMutex);
-
- if (mClient != nullptr) {
- // 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.
- ALOGI("HwcHal::createClient: Client already exists. Waiting for"
- " it to be destroyed.");
- mClientDestroyedWait.wait_for(lock, 1s,
- [this] { return mClient == nullptr; });
- std::string doneMsg = mClient == nullptr ?
- "Existing client was destroyed." :
- "Existing client was never destroyed!";
- ALOGI("HwcHal::createClient: Done waiting. %s", doneMsg.c_str());
- }
-
- // only one client is allowed
- if (mClient == nullptr) {
- client = new ComposerClient(*this);
- client->initialize();
- mClient = client;
- } else {
- err = Error::NO_RESOURCES;
- }
- }
-
- hidl_cb(err, client);
-
- return Void();
-}
-
-sp<ComposerClient> HwcHal::getClient()
-{
- std::lock_guard<std::mutex> lock(mClientMutex);
- return (mClient != nullptr) ? mClient.promote() : nullptr;
-}
-
-void HwcHal::removeClient()
-{
- std::lock_guard<std::mutex> lock(mClientMutex);
- mClient = nullptr;
- mClientDestroyedWait.notify_all();
-}
-
-void HwcHal::hotplugHook(hwc2_callback_data_t callbackData,
- hwc2_display_t display, int32_t connected)
-{
- auto hal = reinterpret_cast<HwcHal*>(callbackData);
- auto client = hal->getClient();
- if (client != nullptr) {
- client->onHotplug(display,
- static_cast<IComposerCallback::Connection>(connected));
- }
-}
-
-void HwcHal::refreshHook(hwc2_callback_data_t callbackData,
- hwc2_display_t display)
-{
- auto hal = reinterpret_cast<HwcHal*>(callbackData);
- hal->mMustValidateDisplay = true;
-
- auto client = hal->getClient();
- if (client != nullptr) {
- client->onRefresh(display);
- }
-}
-
-void HwcHal::vsyncHook(hwc2_callback_data_t callbackData,
- hwc2_display_t display, int64_t timestamp)
-{
- auto hal = reinterpret_cast<HwcHal*>(callbackData);
- auto client = hal->getClient();
- if (client != nullptr) {
- client->onVsync(display, timestamp);
- }
-}
-
-void HwcHal::enableCallback(bool enable)
-{
- if (enable) {
- mMustValidateDisplay = true;
-
- 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));
- } else {
- mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this,
- nullptr);
- mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this,
- nullptr);
- mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this,
- nullptr);
- }
-}
-
-uint32_t HwcHal::getMaxVirtualDisplayCount()
-{
- return mDispatch.getMaxVirtualDisplayCount(mDevice);
-}
-
-Error HwcHal::createVirtualDisplay(uint32_t width, uint32_t height,
- PixelFormat* format, Display* outDisplay)
-{
- 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 HwcHal::destroyVirtualDisplay(Display display)
-{
- int32_t err = mDispatch.destroyVirtualDisplay(mDevice, display);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::createLayer(Display display, Layer* outLayer)
-{
- int32_t err = mDispatch.createLayer(mDevice, display, outLayer);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::destroyLayer(Display display, Layer layer)
-{
- int32_t err = mDispatch.destroyLayer(mDevice, display, layer);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::getActiveConfig(Display display, Config* outConfig)
-{
- int32_t err = mDispatch.getActiveConfig(mDevice, display, outConfig);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::getClientTargetSupport(Display display,
- uint32_t width, uint32_t height,
- PixelFormat format, Dataspace dataspace)
-{
- 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 HwcHal::getColorModes(Display display, hidl_vec<ColorMode>* outModes)
-{
- 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 HwcHal::getDisplayAttribute(Display display, Config config,
- IComposerClient::Attribute attribute, int32_t* outValue)
-{
- int32_t err = mDispatch.getDisplayAttribute(mDevice, display, config,
- static_cast<int32_t>(attribute), outValue);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::getDisplayConfigs(Display display, hidl_vec<Config>* outConfigs)
-{
- 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 HwcHal::getDisplayName(Display display, hidl_string* outName)
-{
- 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 HwcHal::getDisplayType(Display display,
- IComposerClient::DisplayType* outType)
-{
- 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 HwcHal::getDozeSupport(Display display, bool* outSupport)
-{
- int32_t hwc_support = 0;
- int32_t err = mDispatch.getDozeSupport(mDevice, display, &hwc_support);
- *outSupport = hwc_support;
-
- return static_cast<Error>(err);
-}
-
-Error HwcHal::getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes,
- float* outMaxLuminance, float* outMaxAverageLuminance,
- float* outMinLuminance)
-{
- 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 HwcHal::setActiveConfig(Display display, Config config)
-{
- int32_t err = mDispatch.setActiveConfig(mDevice, display, config);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::setColorMode(Display display, ColorMode mode)
-{
- int32_t err = mDispatch.setColorMode(mDevice, display,
- static_cast<int32_t>(mode));
- return static_cast<Error>(err);
-}
-
-Error HwcHal::setPowerMode(Display display, IComposerClient::PowerMode mode)
-{
- int32_t err = mDispatch.setPowerMode(mDevice, display,
- static_cast<int32_t>(mode));
- return static_cast<Error>(err);
-}
-
-Error HwcHal::setVsyncEnabled(Display display, IComposerClient::Vsync enabled)
-{
- int32_t err = mDispatch.setVsyncEnabled(mDevice, display,
- static_cast<int32_t>(enabled));
- return static_cast<Error>(err);
-}
-
-Error HwcHal::setColorTransform(Display display, const float* matrix,
- int32_t hint)
-{
- int32_t err = mDispatch.setColorTransform(mDevice, display, matrix, hint);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::setClientTarget(Display display, buffer_handle_t target,
- int32_t acquireFence, int32_t dataspace,
- const std::vector<hwc_rect_t>& damage)
-{
- hwc_region region = { damage.size(), damage.data() };
- int32_t err = mDispatch.setClientTarget(mDevice, display, target,
- acquireFence, dataspace, region);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::setOutputBuffer(Display display, buffer_handle_t buffer,
- int32_t releaseFence)
-{
- 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 HwcHal::validateDisplay(Display display,
- std::vector<Layer>* outChangedLayers,
- std::vector<IComposerClient::Composition>* outCompositionTypes,
- uint32_t* outDisplayRequestMask,
- std::vector<Layer>* outRequestedLayers,
- std::vector<uint32_t>* outRequestMasks)
-{
- uint32_t types_count = 0;
- uint32_t reqs_count = 0;
- int32_t err = mDispatch.validateDisplay(mDevice, display,
- &types_count, &reqs_count);
- mMustValidateDisplay = false;
-
- if (err != HWC2_ERROR_NONE && err != HWC2_ERROR_HAS_CHANGES) {
- return static_cast<Error>(err);
- }
-
- err = mDispatch.getChangedCompositionTypes(mDevice, display,
- &types_count, nullptr, nullptr);
- if (err != HWC2_ERROR_NONE) {
- return static_cast<Error>(err);
- }
-
- outChangedLayers->resize(types_count);
- outCompositionTypes->resize(types_count);
- err = mDispatch.getChangedCompositionTypes(mDevice, display,
- &types_count, outChangedLayers->data(),
- reinterpret_cast<
- std::underlying_type<IComposerClient::Composition>::type*>(
- outCompositionTypes->data()));
- if (err != HWC2_ERROR_NONE) {
- outChangedLayers->clear();
- outCompositionTypes->clear();
- return static_cast<Error>(err);
- }
-
- int32_t display_reqs = 0;
- err = mDispatch.getDisplayRequests(mDevice, display, &display_reqs,
- &reqs_count, nullptr, nullptr);
- if (err != HWC2_ERROR_NONE) {
- outChangedLayers->clear();
- outCompositionTypes->clear();
- return static_cast<Error>(err);
- }
-
- outRequestedLayers->resize(reqs_count);
- outRequestMasks->resize(reqs_count);
- err = mDispatch.getDisplayRequests(mDevice, display, &display_reqs,
- &reqs_count, outRequestedLayers->data(),
- reinterpret_cast<int32_t*>(outRequestMasks->data()));
- if (err != HWC2_ERROR_NONE) {
- outChangedLayers->clear();
- outCompositionTypes->clear();
-
- outRequestedLayers->clear();
- outRequestMasks->clear();
- return static_cast<Error>(err);
- }
-
- *outDisplayRequestMask = display_reqs;
-
- return static_cast<Error>(err);
-}
-
-Error HwcHal::acceptDisplayChanges(Display display)
-{
- int32_t err = mDispatch.acceptDisplayChanges(mDevice, display);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::presentDisplay(Display display, int32_t* outPresentFence,
- std::vector<Layer>* outLayers, std::vector<int32_t>* outReleaseFences)
-{
- if (mMustValidateDisplay) {
- return Error::NOT_VALIDATED;
- }
-
- *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 HwcHal::setLayerCursorPosition(Display display, Layer layer,
- int32_t x, int32_t y)
-{
- int32_t err = mDispatch.setCursorPosition(mDevice, display, layer, x, y);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerBuffer(Display display, Layer layer,
- buffer_handle_t buffer, int32_t acquireFence)
-{
- int32_t err = mDispatch.setLayerBuffer(mDevice, display, layer,
- buffer, acquireFence);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerSurfaceDamage(Display display, Layer layer,
- const std::vector<hwc_rect_t>& damage)
-{
- hwc_region region = { damage.size(), damage.data() };
- int32_t err = mDispatch.setLayerSurfaceDamage(mDevice, display, layer,
- region);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerBlendMode(Display display, Layer layer, int32_t mode)
-{
- int32_t err = mDispatch.setLayerBlendMode(mDevice, display, layer, mode);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerColor(Display display, Layer layer,
- IComposerClient::Color color)
-{
- 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 HwcHal::setLayerCompositionType(Display display, Layer layer,
- int32_t type)
-{
- int32_t err = mDispatch.setLayerCompositionType(mDevice, display, layer,
- type);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerDataspace(Display display, Layer layer,
- int32_t dataspace)
-{
- int32_t err = mDispatch.setLayerDataspace(mDevice, display, layer,
- dataspace);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerDisplayFrame(Display display, Layer layer,
- const hwc_rect_t& frame)
-{
- int32_t err = mDispatch.setLayerDisplayFrame(mDevice, display, layer,
- frame);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerPlaneAlpha(Display display, Layer layer, float alpha)
-{
- int32_t err = mDispatch.setLayerPlaneAlpha(mDevice, display, layer,
- alpha);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerSidebandStream(Display display, Layer layer,
- buffer_handle_t stream)
-{
- int32_t err = mDispatch.setLayerSidebandStream(mDevice, display, layer,
- stream);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerSourceCrop(Display display, Layer layer,
- const hwc_frect_t& crop)
-{
- int32_t err = mDispatch.setLayerSourceCrop(mDevice, display, layer, crop);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerTransform(Display display, Layer layer,
- int32_t transform)
-{
- int32_t err = mDispatch.setLayerTransform(mDevice, display, layer,
- transform);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerVisibleRegion(Display display, Layer layer,
- const std::vector<hwc_rect_t>& visible)
-{
- hwc_region_t region = { visible.size(), visible.data() };
- int32_t err = mDispatch.setLayerVisibleRegion(mDevice, display, layer,
- region);
- return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerZOrder(Display display, Layer layer, uint32_t z)
-{
- int32_t err = mDispatch.setLayerZOrder(mDevice, display, layer, z);
- return static_cast<Error>(err);
-}
-
-IComposer* HIDL_FETCH_IComposer(const char*)
-{
- const hw_module_t* module = nullptr;
- int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &module);
- if (err) {
- ALOGI("falling back to FB HAL");
- err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
- }
- if (err) {
- ALOGE("failed to get hwcomposer or fb module");
- return nullptr;
- }
-
- return new HwcHal(module);
-}
-
-} // namespace implementation
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/composer/2.1/default/Hwc.h b/graphics/composer/2.1/default/Hwc.h
deleted file mode 100644
index e3f5ce6..0000000
--- a/graphics/composer/2.1/default/Hwc.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
-#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
-
-#include <atomic>
-#include <condition_variable>
-#include <memory>
-#include <mutex>
-#include <unordered_set>
-#include <vector>
-
-#include <android/hardware/graphics/composer/2.1/IComposer.h>
-#define HWC2_INCLUDE_STRINGIFICATION
-#define HWC2_USE_CPP11
-#include <hardware/hwcomposer2.h>
-#undef HWC2_INCLUDE_STRINGIFICATION
-#undef HWC2_USE_CPP11
-#include "ComposerBase.h"
-
-namespace android {
- class HWC2On1Adapter;
- class HWC2OnFbAdapter;
-}
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace implementation {
-
-using android::hardware::graphics::common::V1_0::PixelFormat;
-using android::hardware::graphics::common::V1_0::Transform;
-using android::hardware::graphics::common::V1_0::Dataspace;
-using android::hardware::graphics::common::V1_0::ColorMode;
-using android::hardware::graphics::common::V1_0::ColorTransform;
-using android::hardware::graphics::common::V1_0::Hdr;
-
-class ComposerClient;
-
-class HwcHal : public IComposer, public ComposerBase {
-public:
- HwcHal(const hw_module_t* module);
- virtual ~HwcHal();
-
- // IComposer interface
- Return<void> getCapabilities(getCapabilities_cb hidl_cb) override;
- Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
- Return<void> createClient(createClient_cb hidl_cb) override;
-
- // ComposerBase interface
- bool hasCapability(hwc2_capability_t capability) override;
- void removeClient() override;
- void enableCallback(bool enable) override;
- uint32_t getMaxVirtualDisplayCount() override;
- Error createVirtualDisplay(uint32_t width, uint32_t height,
- PixelFormat* format, Display* outDisplay) override;
- Error destroyVirtualDisplay(Display display) override;
-
- Error createLayer(Display display, Layer* outLayer) override;
- Error destroyLayer(Display display, Layer layer) override;
-
- Error getActiveConfig(Display display, Config* outConfig) override;
- Error getClientTargetSupport(Display display,
- uint32_t width, uint32_t height,
- PixelFormat format, Dataspace dataspace) override;
- Error getColorModes(Display display,
- hidl_vec<ColorMode>* outModes) override;
- Error getDisplayAttribute(Display display, Config config,
- IComposerClient::Attribute attribute, int32_t* outValue) override;
- Error getDisplayConfigs(Display display,
- hidl_vec<Config>* outConfigs) override;
- Error getDisplayName(Display display, hidl_string* outName) override;
- Error getDisplayType(Display display,
- IComposerClient::DisplayType* outType) override;
- Error getDozeSupport(Display display, bool* outSupport) override;
- Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes,
- float* outMaxLuminance, float* outMaxAverageLuminance,
- float* outMinLuminance) override;
-
- Error setActiveConfig(Display display, Config config) override;
- Error setColorMode(Display display, ColorMode mode) override;
- Error setPowerMode(Display display,
- IComposerClient::PowerMode mode) override;
- Error setVsyncEnabled(Display display,
- IComposerClient::Vsync enabled) override;
-
- Error setColorTransform(Display display, const float* matrix,
- int32_t hint) override;
- Error setClientTarget(Display display, buffer_handle_t target,
- int32_t acquireFence, int32_t dataspace,
- const std::vector<hwc_rect_t>& damage) override;
- Error setOutputBuffer(Display display, buffer_handle_t buffer,
- int32_t releaseFence) override;
- 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;
- Error acceptDisplayChanges(Display display) override;
- Error presentDisplay(Display display, int32_t* outPresentFence,
- std::vector<Layer>* outLayers,
- std::vector<int32_t>* outReleaseFences) override;
-
- Error setLayerCursorPosition(Display display, Layer layer,
- int32_t x, int32_t y) override;
- Error setLayerBuffer(Display display, Layer layer,
- buffer_handle_t buffer, int32_t acquireFence) override;
- Error setLayerSurfaceDamage(Display display, Layer layer,
- const std::vector<hwc_rect_t>& damage) override;
- Error setLayerBlendMode(Display display, Layer layer,
- int32_t mode) override;
- Error setLayerColor(Display display, Layer layer,
- IComposerClient::Color color) override;
- Error setLayerCompositionType(Display display, Layer layer,
- int32_t type) override;
- Error setLayerDataspace(Display display, Layer layer,
- int32_t dataspace) override;
- Error setLayerDisplayFrame(Display display, Layer layer,
- const hwc_rect_t& frame) override;
- Error setLayerPlaneAlpha(Display display, Layer layer,
- float alpha) override;
- Error setLayerSidebandStream(Display display, Layer layer,
- buffer_handle_t stream) override;
- Error setLayerSourceCrop(Display display, Layer layer,
- const hwc_frect_t& crop) override;
- Error setLayerTransform(Display display, Layer layer,
- int32_t transform) override;
- Error setLayerVisibleRegion(Display display, Layer layer,
- const std::vector<hwc_rect_t>& visible) override;
- Error setLayerZOrder(Display display, Layer layer, uint32_t z) override;
-
-private:
- uint32_t initWithHwc(const hw_module_t* module);
- uint32_t initWithFb(const hw_module_t* module);
-
- void initCapabilities();
-
- template<typename T>
- void initDispatch(hwc2_function_descriptor_t desc, T* outPfn);
- void initDispatch();
-
- sp<ComposerClient> getClient();
-
- static void hotplugHook(hwc2_callback_data_t callbackData,
- hwc2_display_t display, int32_t connected);
- static void refreshHook(hwc2_callback_data_t callbackData,
- hwc2_display_t display);
- static void vsyncHook(hwc2_callback_data_t callbackData,
- hwc2_display_t display, int64_t timestamp);
-
- hwc2_device_t* mDevice;
-
- 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;
-
- std::mutex mClientMutex;
- std::condition_variable mClientDestroyedWait;
- wp<ComposerClient> mClient;
-
- std::atomic<bool> mMustValidateDisplay;
-
- // If the HWC implementation version is < 2.0, use an adapter to interface
- // between HWC 2.0 <-> HWC 1.X.
- std::unique_ptr<HWC2On1Adapter> mAdapter;
-
- // If there is no HWC implementation, use an adapter to interface between
- // HWC 2.0 <-> FB HAL.
- std::unique_ptr<HWC2OnFbAdapter> mFbAdapter;
-};
-
-extern "C" IComposer* HIDL_FETCH_IComposer(const char* name);
-
-} // namespace implementation
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
diff --git a/graphics/composer/2.1/default/passthrough.cpp b/graphics/composer/2.1/default/passthrough.cpp
new file mode 100644
index 0000000..ef7ed7c
--- /dev/null
+++ b/graphics/composer/2.1/default/passthrough.cpp
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+#include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <composer-passthrough/2.1/HwcLoader.h>
+
+using android::hardware::graphics::composer::V2_1::IComposer;
+using android::hardware::graphics::composer::V2_1::passthrough::HwcLoader;
+
+extern "C" IComposer* HIDL_FETCH_IComposer(const char* /* name */) {
+ return HwcLoader::load();
+}
diff --git a/graphics/composer/2.1/utils/command-buffer/Android.bp b/graphics/composer/2.1/utils/command-buffer/Android.bp
index e8d41c2..140d9bb 100644
--- a/graphics/composer/2.1/utils/command-buffer/Android.bp
+++ b/graphics/composer/2.1/utils/command-buffer/Android.bp
@@ -2,6 +2,15 @@
name: "android.hardware.graphics.composer@2.1-command-buffer",
defaults: ["hidl_defaults"],
vendor_available: true,
- shared_libs: ["android.hardware.graphics.composer@2.1"],
+ shared_libs: [
+ "android.hardware.graphics.composer@2.1",
+ "libfmq",
+ "libsync",
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.graphics.composer@2.1",
+ "libfmq",
+ "libsync",
+ ],
export_include_dirs: ["include"],
}
diff --git a/graphics/composer/2.1/utils/hal/Android.bp b/graphics/composer/2.1/utils/hal/Android.bp
new file mode 100644
index 0000000..f24e768
--- /dev/null
+++ b/graphics/composer/2.1/utils/hal/Android.bp
@@ -0,0 +1,37 @@
+//
+// 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",
+ "libhardware", // TODO remove hwcomposer2.h dependency
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.mapper@2.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/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h
new file mode 100644
index 0000000..581dc96
--- /dev/null
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h
@@ -0,0 +1,157 @@
+/*
+ * 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);
+ if (!waitForClientDestroyedLocked(lock)) {
+ 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.promote() == nullptr; });
+ if (mClient.promote() != nullptr) {
+ ALOGD("previous client was not destroyed");
+ } else {
+ mClient.clear();
+ }
+ }
+
+ 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/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h
new file mode 100644
index 0000000..86525b8
--- /dev/null
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h
@@ -0,0 +1,396 @@
+/*
+ * 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) {
+ 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/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h
new file mode 100644
index 0000000..36aa64e
--- /dev/null
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h
@@ -0,0 +1,594 @@
+/*
+ * 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);
+ 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 = 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);
+ 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/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerHal.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerHal.h
new file mode 100644
index 0000000..c9793fd
--- /dev/null
+++ b/graphics/composer/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/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
new file mode 100644
index 0000000..7bb3692
--- /dev/null
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
@@ -0,0 +1,536 @@
+/*
+ * 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 <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() {
+ mMapper = mapper::V2_0::IMapper::getService();
+ ALOGE_IF(!mMapper, "failed to get mapper service");
+ return mMapper != nullptr;
+ }
+
+ Error importBuffer(const native_handle_t* rawHandle, const native_handle_t** outBufferHandle) {
+ if (!rawHandle || (!rawHandle->numFds && !rawHandle->numInts)) {
+ *outBufferHandle = nullptr;
+ return Error::NONE;
+ }
+
+ mapper::V2_0::Error error;
+ const native_handle_t* bufferHandle;
+ mMapper->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;
+ }
+
+ *outBufferHandle = bufferHandle;
+ return Error::NONE;
+ }
+
+ void freeBuffer(const native_handle_t* bufferHandle) {
+ if (bufferHandle) {
+ mMapper->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> mMapper;
+};
+
+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 < 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 < 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) {}
+
+ 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,
+ };
+
+ ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer,
+ uint32_t outputBufferCacheSize)
+ : mType(type),
+ mClientTargetCache(importer),
+ mOutputBufferCache(importer, ComposerHandleCache::HandleType::BUFFER,
+ outputBufferCacheSize) {}
+
+ 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;
+ }
+
+ protected:
+ const DisplayType mType;
+ ComposerHandleCache mClientTargetCache;
+ ComposerHandleCache mOutputBufferCache;
+
+ 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);
+ }
+
+ 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/graphics/composer/2.1/utils/hwc2on1adapter/Android.bp b/graphics/composer/2.1/utils/hwc2on1adapter/Android.bp
new file mode 100644
index 0000000..420a1f6
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/Android.bp
@@ -0,0 +1,76 @@
+// Copyright 2010 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_shared {
+ name: "libhwc2on1adapter",
+ vendor: true,
+
+ clang: true,
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-user-defined-warnings",
+ ],
+ cppflags: [
+ "-Weverything",
+ "-Wunused",
+ "-Wunreachable-code",
+
+ // The static constructors and destructors in this library have not been noted to
+ // introduce significant overheads
+ "-Wno-exit-time-destructors",
+ "-Wno-global-constructors",
+
+ // We only care about compiling as C++14
+ "-Wno-c++98-compat-pedantic",
+
+ // android/sensors.h uses nested anonymous unions and anonymous structs
+ "-Wno-nested-anon-types",
+ "-Wno-gnu-anonymous-struct",
+
+ // Don't warn about struct padding
+ "-Wno-padded",
+
+ // hwcomposer2.h features switch covering all cases.
+ "-Wno-covered-switch-default",
+
+ // hwcomposer.h features zero size array.
+ "-Wno-zero-length-array",
+
+ // Disabling warning specific to hwc2on1adapter code
+ "-Wno-double-promotion",
+ "-Wno-sign-conversion",
+ "-Wno-switch-enum",
+ "-Wno-float-equal",
+ "-Wno-shorten-64-to-32",
+ "-Wno-sign-compare",
+ "-Wno-missing-prototypes",
+ ],
+
+ srcs: [
+ "HWC2On1Adapter.cpp",
+ "MiniFence.cpp",
+ ],
+
+ shared_libs: [
+ "libutils",
+ "libcutils",
+ "liblog",
+ "libhardware",
+ ],
+
+ export_include_dirs: ["include"],
+
+ export_shared_lib_headers: ["libutils"],
+}
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/CleanSpec.mk b/graphics/composer/2.1/utils/hwc2on1adapter/CleanSpec.mk
new file mode 100644
index 0000000..7fc2216
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/CleanSpec.mk
@@ -0,0 +1,52 @@
+# Copyright (C) 2017 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.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list. These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list. E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libhwc2on1adapter_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libhwc2on1adapter.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/libhwc2on1adapter.so)
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp b/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp
new file mode 100644
index 0000000..77f06bb
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp
@@ -0,0 +1,2637 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "hwc2on1adapter/HWC2On1Adapter.h"
+
+//#define LOG_NDEBUG 0
+
+#undef LOG_TAG
+#define LOG_TAG "HWC2On1Adapter"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+
+#include <inttypes.h>
+
+#include <chrono>
+#include <cstdlib>
+#include <sstream>
+
+#include <hardware/hwcomposer.h>
+#include <log/log.h>
+#include <utils/Trace.h>
+
+using namespace std::chrono_literals;
+
+static uint8_t getMinorVersion(struct hwc_composer_device_1* device)
+{
+ auto version = device->common.version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
+ return (version >> 16) & 0xF;
+}
+
+template <typename PFN, typename T>
+static hwc2_function_pointer_t asFP(T function)
+{
+ static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
+ return reinterpret_cast<hwc2_function_pointer_t>(function);
+}
+
+using namespace HWC2;
+
+static constexpr Attribute ColorMode = static_cast<Attribute>(6);
+
+namespace android {
+
+class HWC2On1Adapter::Callbacks : public hwc_procs_t {
+ public:
+ explicit Callbacks(HWC2On1Adapter& adapter) : mAdapter(adapter) {
+ invalidate = &invalidateHook;
+ vsync = &vsyncHook;
+ hotplug = &hotplugHook;
+ }
+
+ static void invalidateHook(const hwc_procs_t* procs) {
+ auto callbacks = static_cast<const Callbacks*>(procs);
+ callbacks->mAdapter.hwc1Invalidate();
+ }
+
+ static void vsyncHook(const hwc_procs_t* procs, int display,
+ int64_t timestamp) {
+ auto callbacks = static_cast<const Callbacks*>(procs);
+ callbacks->mAdapter.hwc1Vsync(display, timestamp);
+ }
+
+ static void hotplugHook(const hwc_procs_t* procs, int display,
+ int connected) {
+ auto callbacks = static_cast<const Callbacks*>(procs);
+ callbacks->mAdapter.hwc1Hotplug(display, connected);
+ }
+
+ private:
+ HWC2On1Adapter& mAdapter;
+};
+
+static int closeHook(hw_device_t* /*device*/)
+{
+ // Do nothing, since the real work is done in the class destructor, but we
+ // need to provide a valid function pointer for hwc2_close to call
+ return 0;
+}
+
+HWC2On1Adapter::HWC2On1Adapter(hwc_composer_device_1_t* hwc1Device)
+ : mDumpString(),
+ mHwc1Device(hwc1Device),
+ mHwc1MinorVersion(getMinorVersion(hwc1Device)),
+ mHwc1SupportsVirtualDisplays(false),
+ mHwc1SupportsBackgroundColor(false),
+ mHwc1Callbacks(std::make_unique<Callbacks>(*this)),
+ mCapabilities(),
+ mLayers(),
+ mHwc1VirtualDisplay(),
+ mStateMutex(),
+ mCallbacks(),
+ mHasPendingInvalidate(false),
+ mPendingVsyncs(),
+ mPendingHotplugs(),
+ mDisplays(),
+ mHwc1DisplayMap()
+{
+ common.close = closeHook;
+ getCapabilities = getCapabilitiesHook;
+ getFunction = getFunctionHook;
+ populateCapabilities();
+ populatePrimary();
+ mHwc1Device->registerProcs(mHwc1Device,
+ static_cast<const hwc_procs_t*>(mHwc1Callbacks.get()));
+}
+
+HWC2On1Adapter::~HWC2On1Adapter() {
+ hwc_close_1(mHwc1Device);
+}
+
+void HWC2On1Adapter::doGetCapabilities(uint32_t* outCount,
+ int32_t* outCapabilities) {
+ if (outCapabilities == nullptr) {
+ *outCount = mCapabilities.size();
+ return;
+ }
+
+ auto capabilityIter = mCapabilities.cbegin();
+ for (size_t written = 0; written < *outCount; ++written) {
+ if (capabilityIter == mCapabilities.cend()) {
+ return;
+ }
+ outCapabilities[written] = static_cast<int32_t>(*capabilityIter);
+ ++capabilityIter;
+ }
+}
+
+hwc2_function_pointer_t HWC2On1Adapter::doGetFunction(
+ FunctionDescriptor descriptor) {
+ switch (descriptor) {
+ // Device functions
+ case FunctionDescriptor::CreateVirtualDisplay:
+ return asFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(
+ createVirtualDisplayHook);
+ case FunctionDescriptor::DestroyVirtualDisplay:
+ return asFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(
+ destroyVirtualDisplayHook);
+ case FunctionDescriptor::Dump:
+ return asFP<HWC2_PFN_DUMP>(dumpHook);
+ case FunctionDescriptor::GetMaxVirtualDisplayCount:
+ return asFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(
+ getMaxVirtualDisplayCountHook);
+ case FunctionDescriptor::RegisterCallback:
+ return asFP<HWC2_PFN_REGISTER_CALLBACK>(registerCallbackHook);
+
+ // Display functions
+ case FunctionDescriptor::AcceptDisplayChanges:
+ return asFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(
+ displayHook<decltype(&Display::acceptChanges),
+ &Display::acceptChanges>);
+ case FunctionDescriptor::CreateLayer:
+ return asFP<HWC2_PFN_CREATE_LAYER>(
+ displayHook<decltype(&Display::createLayer),
+ &Display::createLayer, hwc2_layer_t*>);
+ case FunctionDescriptor::DestroyLayer:
+ return asFP<HWC2_PFN_DESTROY_LAYER>(
+ displayHook<decltype(&Display::destroyLayer),
+ &Display::destroyLayer, hwc2_layer_t>);
+ case FunctionDescriptor::GetActiveConfig:
+ return asFP<HWC2_PFN_GET_ACTIVE_CONFIG>(
+ displayHook<decltype(&Display::getActiveConfig),
+ &Display::getActiveConfig, hwc2_config_t*>);
+ case FunctionDescriptor::GetChangedCompositionTypes:
+ return asFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(
+ displayHook<decltype(&Display::getChangedCompositionTypes),
+ &Display::getChangedCompositionTypes, uint32_t*,
+ hwc2_layer_t*, int32_t*>);
+ case FunctionDescriptor::GetColorModes:
+ return asFP<HWC2_PFN_GET_COLOR_MODES>(
+ displayHook<decltype(&Display::getColorModes),
+ &Display::getColorModes, uint32_t*, int32_t*>);
+ case FunctionDescriptor::GetDisplayAttribute:
+ return asFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(
+ getDisplayAttributeHook);
+ case FunctionDescriptor::GetDisplayConfigs:
+ return asFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(
+ displayHook<decltype(&Display::getConfigs),
+ &Display::getConfigs, uint32_t*, hwc2_config_t*>);
+ case FunctionDescriptor::GetDisplayName:
+ return asFP<HWC2_PFN_GET_DISPLAY_NAME>(
+ displayHook<decltype(&Display::getName),
+ &Display::getName, uint32_t*, char*>);
+ case FunctionDescriptor::GetDisplayRequests:
+ return asFP<HWC2_PFN_GET_DISPLAY_REQUESTS>(
+ displayHook<decltype(&Display::getRequests),
+ &Display::getRequests, int32_t*, uint32_t*, hwc2_layer_t*,
+ int32_t*>);
+ case FunctionDescriptor::GetDisplayType:
+ return asFP<HWC2_PFN_GET_DISPLAY_TYPE>(
+ displayHook<decltype(&Display::getType),
+ &Display::getType, int32_t*>);
+ case FunctionDescriptor::GetDozeSupport:
+ return asFP<HWC2_PFN_GET_DOZE_SUPPORT>(
+ displayHook<decltype(&Display::getDozeSupport),
+ &Display::getDozeSupport, int32_t*>);
+ case FunctionDescriptor::GetHdrCapabilities:
+ return asFP<HWC2_PFN_GET_HDR_CAPABILITIES>(
+ displayHook<decltype(&Display::getHdrCapabilities),
+ &Display::getHdrCapabilities, uint32_t*, int32_t*, float*,
+ float*, float*>);
+ case FunctionDescriptor::GetReleaseFences:
+ return asFP<HWC2_PFN_GET_RELEASE_FENCES>(
+ displayHook<decltype(&Display::getReleaseFences),
+ &Display::getReleaseFences, uint32_t*, hwc2_layer_t*,
+ int32_t*>);
+ case FunctionDescriptor::PresentDisplay:
+ return asFP<HWC2_PFN_PRESENT_DISPLAY>(
+ displayHook<decltype(&Display::present),
+ &Display::present, int32_t*>);
+ case FunctionDescriptor::SetActiveConfig:
+ return asFP<HWC2_PFN_SET_ACTIVE_CONFIG>(
+ displayHook<decltype(&Display::setActiveConfig),
+ &Display::setActiveConfig, hwc2_config_t>);
+ case FunctionDescriptor::SetClientTarget:
+ return asFP<HWC2_PFN_SET_CLIENT_TARGET>(
+ displayHook<decltype(&Display::setClientTarget),
+ &Display::setClientTarget, buffer_handle_t, int32_t,
+ int32_t, hwc_region_t>);
+ case FunctionDescriptor::SetColorMode:
+ return asFP<HWC2_PFN_SET_COLOR_MODE>(setColorModeHook);
+ case FunctionDescriptor::SetColorTransform:
+ return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(setColorTransformHook);
+ case FunctionDescriptor::SetOutputBuffer:
+ return asFP<HWC2_PFN_SET_OUTPUT_BUFFER>(
+ displayHook<decltype(&Display::setOutputBuffer),
+ &Display::setOutputBuffer, buffer_handle_t, int32_t>);
+ case FunctionDescriptor::SetPowerMode:
+ return asFP<HWC2_PFN_SET_POWER_MODE>(setPowerModeHook);
+ case FunctionDescriptor::SetVsyncEnabled:
+ return asFP<HWC2_PFN_SET_VSYNC_ENABLED>(setVsyncEnabledHook);
+ case FunctionDescriptor::ValidateDisplay:
+ return asFP<HWC2_PFN_VALIDATE_DISPLAY>(
+ displayHook<decltype(&Display::validate),
+ &Display::validate, uint32_t*, uint32_t*>);
+ case FunctionDescriptor::GetClientTargetSupport:
+ return asFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(
+ displayHook<decltype(&Display::getClientTargetSupport),
+ &Display::getClientTargetSupport, uint32_t, uint32_t,
+ int32_t, int32_t>);
+
+ // Layer functions
+ case FunctionDescriptor::SetCursorPosition:
+ return asFP<HWC2_PFN_SET_CURSOR_POSITION>(
+ layerHook<decltype(&Layer::setCursorPosition),
+ &Layer::setCursorPosition, int32_t, int32_t>);
+ case FunctionDescriptor::SetLayerBuffer:
+ return asFP<HWC2_PFN_SET_LAYER_BUFFER>(
+ layerHook<decltype(&Layer::setBuffer), &Layer::setBuffer,
+ buffer_handle_t, int32_t>);
+ case FunctionDescriptor::SetLayerSurfaceDamage:
+ return asFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(
+ layerHook<decltype(&Layer::setSurfaceDamage),
+ &Layer::setSurfaceDamage, hwc_region_t>);
+
+ // Layer state functions
+ case FunctionDescriptor::SetLayerBlendMode:
+ return asFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(
+ setLayerBlendModeHook);
+ case FunctionDescriptor::SetLayerColor:
+ return asFP<HWC2_PFN_SET_LAYER_COLOR>(
+ layerHook<decltype(&Layer::setColor), &Layer::setColor,
+ hwc_color_t>);
+ case FunctionDescriptor::SetLayerCompositionType:
+ return asFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(
+ setLayerCompositionTypeHook);
+ case FunctionDescriptor::SetLayerDataspace:
+ return asFP<HWC2_PFN_SET_LAYER_DATASPACE>(setLayerDataspaceHook);
+ case FunctionDescriptor::SetLayerDisplayFrame:
+ return asFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(
+ layerHook<decltype(&Layer::setDisplayFrame),
+ &Layer::setDisplayFrame, hwc_rect_t>);
+ case FunctionDescriptor::SetLayerPlaneAlpha:
+ return asFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(
+ layerHook<decltype(&Layer::setPlaneAlpha),
+ &Layer::setPlaneAlpha, float>);
+ case FunctionDescriptor::SetLayerSidebandStream:
+ return asFP<HWC2_PFN_SET_LAYER_SIDEBAND_STREAM>(
+ layerHook<decltype(&Layer::setSidebandStream),
+ &Layer::setSidebandStream, const native_handle_t*>);
+ case FunctionDescriptor::SetLayerSourceCrop:
+ return asFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(
+ layerHook<decltype(&Layer::setSourceCrop),
+ &Layer::setSourceCrop, hwc_frect_t>);
+ case FunctionDescriptor::SetLayerTransform:
+ return asFP<HWC2_PFN_SET_LAYER_TRANSFORM>(setLayerTransformHook);
+ case FunctionDescriptor::SetLayerVisibleRegion:
+ return asFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(
+ layerHook<decltype(&Layer::setVisibleRegion),
+ &Layer::setVisibleRegion, hwc_region_t>);
+ case FunctionDescriptor::SetLayerZOrder:
+ return asFP<HWC2_PFN_SET_LAYER_Z_ORDER>(setLayerZOrderHook);
+
+ default:
+ ALOGE("doGetFunction: Unknown function descriptor: %d (%s)",
+ static_cast<int32_t>(descriptor),
+ to_string(descriptor).c_str());
+ return nullptr;
+ }
+}
+
+// Device functions
+
+Error HWC2On1Adapter::createVirtualDisplay(uint32_t width,
+ uint32_t height, hwc2_display_t* outDisplay) {
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+ if (mHwc1VirtualDisplay) {
+ // We have already allocated our only HWC1 virtual display
+ ALOGE("createVirtualDisplay: HWC1 virtual display already allocated");
+ return Error::NoResources;
+ }
+
+ mHwc1VirtualDisplay = std::make_shared<HWC2On1Adapter::Display>(*this,
+ HWC2::DisplayType::Virtual);
+ mHwc1VirtualDisplay->populateConfigs(width, height);
+ const auto displayId = mHwc1VirtualDisplay->getId();
+ mHwc1DisplayMap[HWC_DISPLAY_VIRTUAL] = displayId;
+ mHwc1VirtualDisplay->setHwc1Id(HWC_DISPLAY_VIRTUAL);
+ mDisplays.emplace(displayId, mHwc1VirtualDisplay);
+ *outDisplay = displayId;
+
+ return Error::None;
+}
+
+Error HWC2On1Adapter::destroyVirtualDisplay(hwc2_display_t displayId) {
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+ if (!mHwc1VirtualDisplay || (mHwc1VirtualDisplay->getId() != displayId)) {
+ return Error::BadDisplay;
+ }
+
+ mHwc1VirtualDisplay.reset();
+ mHwc1DisplayMap.erase(HWC_DISPLAY_VIRTUAL);
+ mDisplays.erase(displayId);
+
+ return Error::None;
+}
+
+void HWC2On1Adapter::dump(uint32_t* outSize, char* outBuffer) {
+ if (outBuffer != nullptr) {
+ auto copiedBytes = mDumpString.copy(outBuffer, *outSize);
+ *outSize = static_cast<uint32_t>(copiedBytes);
+ return;
+ }
+
+ std::stringstream output;
+
+ output << "-- HWC2On1Adapter --\n";
+
+ output << "Adapting to a HWC 1." << static_cast<int>(mHwc1MinorVersion) <<
+ " device\n";
+
+ // Attempt to acquire the lock for 1 second, but proceed without the lock
+ // after that, so we can still get some information if we're deadlocked
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex,
+ std::defer_lock);
+ lock.try_lock_for(1s);
+
+ if (mCapabilities.empty()) {
+ output << "Capabilities: None\n";
+ } else {
+ output << "Capabilities:\n";
+ for (auto capability : mCapabilities) {
+ output << " " << to_string(capability) << '\n';
+ }
+ }
+
+ output << "Displays:\n";
+ for (const auto& element : mDisplays) {
+ const auto& display = element.second;
+ output << display->dump();
+ }
+ output << '\n';
+
+ // Release the lock before calling into HWC1, and since we no longer require
+ // mutual exclusion to access mCapabilities or mDisplays
+ lock.unlock();
+
+ if (mHwc1Device->dump) {
+ output << "HWC1 dump:\n";
+ std::vector<char> hwc1Dump(4096);
+ // Call with size - 1 to preserve a null character at the end
+ mHwc1Device->dump(mHwc1Device, hwc1Dump.data(),
+ static_cast<int>(hwc1Dump.size() - 1));
+ output << hwc1Dump.data();
+ }
+
+ mDumpString = output.str();
+ *outSize = static_cast<uint32_t>(mDumpString.size());
+}
+
+uint32_t HWC2On1Adapter::getMaxVirtualDisplayCount() {
+ return mHwc1SupportsVirtualDisplays ? 1 : 0;
+}
+
+static bool isValid(Callback descriptor) {
+ switch (descriptor) {
+ case Callback::Hotplug: // Fall-through
+ case Callback::Refresh: // Fall-through
+ case Callback::Vsync: return true;
+ default: return false;
+ }
+}
+
+Error HWC2On1Adapter::registerCallback(Callback descriptor,
+ hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) {
+ if (!isValid(descriptor)) {
+ return Error::BadParameter;
+ }
+
+ ALOGV("registerCallback(%s, %p, %p)", to_string(descriptor).c_str(),
+ callbackData, pointer);
+
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+ if (pointer != nullptr) {
+ mCallbacks[descriptor] = {callbackData, pointer};
+ } else {
+ ALOGI("unregisterCallback(%s)", to_string(descriptor).c_str());
+ mCallbacks.erase(descriptor);
+ return Error::None;
+ }
+
+ bool hasPendingInvalidate = false;
+ std::vector<hwc2_display_t> displayIds;
+ std::vector<std::pair<hwc2_display_t, int64_t>> pendingVsyncs;
+ std::vector<std::pair<hwc2_display_t, int>> pendingHotplugs;
+
+ if (descriptor == Callback::Refresh) {
+ hasPendingInvalidate = mHasPendingInvalidate;
+ if (hasPendingInvalidate) {
+ for (auto& displayPair : mDisplays) {
+ displayIds.emplace_back(displayPair.first);
+ }
+ }
+ mHasPendingInvalidate = false;
+ } else if (descriptor == Callback::Vsync) {
+ for (auto pending : mPendingVsyncs) {
+ auto hwc1DisplayId = pending.first;
+ if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
+ ALOGE("hwc1Vsync: Couldn't find display for HWC1 id %d",
+ hwc1DisplayId);
+ continue;
+ }
+ auto displayId = mHwc1DisplayMap[hwc1DisplayId];
+ auto timestamp = pending.second;
+ pendingVsyncs.emplace_back(displayId, timestamp);
+ }
+ mPendingVsyncs.clear();
+ } else if (descriptor == Callback::Hotplug) {
+ // Hotplug the primary display
+ pendingHotplugs.emplace_back(mHwc1DisplayMap[HWC_DISPLAY_PRIMARY],
+ static_cast<int32_t>(Connection::Connected));
+
+ for (auto pending : mPendingHotplugs) {
+ auto hwc1DisplayId = pending.first;
+ if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
+ ALOGE("hwc1Hotplug: Couldn't find display for HWC1 id %d",
+ hwc1DisplayId);
+ continue;
+ }
+ auto displayId = mHwc1DisplayMap[hwc1DisplayId];
+ auto connected = pending.second;
+ pendingHotplugs.emplace_back(displayId, connected);
+ }
+ }
+
+ // Call pending callbacks without the state lock held
+ lock.unlock();
+
+ if (hasPendingInvalidate) {
+ auto refresh = reinterpret_cast<HWC2_PFN_REFRESH>(pointer);
+ for (auto displayId : displayIds) {
+ refresh(callbackData, displayId);
+ }
+ }
+ if (!pendingVsyncs.empty()) {
+ auto vsync = reinterpret_cast<HWC2_PFN_VSYNC>(pointer);
+ for (auto& pendingVsync : pendingVsyncs) {
+ vsync(callbackData, pendingVsync.first, pendingVsync.second);
+ }
+ }
+ if (!pendingHotplugs.empty()) {
+ auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(pointer);
+ for (auto& pendingHotplug : pendingHotplugs) {
+ hotplug(callbackData, pendingHotplug.first, pendingHotplug.second);
+ }
+ }
+ return Error::None;
+}
+
+// Display functions
+
+std::atomic<hwc2_display_t> HWC2On1Adapter::Display::sNextId(1);
+
+HWC2On1Adapter::Display::Display(HWC2On1Adapter& device, HWC2::DisplayType type)
+ : mId(sNextId++),
+ mDevice(device),
+ mStateMutex(),
+ mHwc1RequestedContents(nullptr),
+ mRetireFence(),
+ mChanges(),
+ mHwc1Id(-1),
+ mConfigs(),
+ mActiveConfig(nullptr),
+ mActiveColorMode(static_cast<android_color_mode_t>(-1)),
+ mName(),
+ mType(type),
+ mPowerMode(PowerMode::Off),
+ mVsyncEnabled(Vsync::Invalid),
+ mClientTarget(),
+ mOutputBuffer(),
+ mHasColorTransform(false),
+ mLayers(),
+ mHwc1LayerMap(),
+ mNumAvailableRects(0),
+ mNextAvailableRect(nullptr),
+ mGeometryChanged(false)
+ {}
+
+Error HWC2On1Adapter::Display::acceptChanges() {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (!mChanges) {
+ ALOGV("[%" PRIu64 "] acceptChanges failed, not validated", mId);
+ return Error::NotValidated;
+ }
+
+ ALOGV("[%" PRIu64 "] acceptChanges", mId);
+
+ for (auto& change : mChanges->getTypeChanges()) {
+ auto layerId = change.first;
+ auto type = change.second;
+ if (mDevice.mLayers.count(layerId) == 0) {
+ // This should never happen but somehow does.
+ ALOGW("Cannot accept change for unknown layer (%" PRIu64 ")",
+ layerId);
+ continue;
+ }
+ auto layer = mDevice.mLayers[layerId];
+ layer->setCompositionType(type);
+ }
+
+ mChanges->clearTypeChanges();
+
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::createLayer(hwc2_layer_t* outLayerId) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ auto layer = *mLayers.emplace(std::make_shared<Layer>(*this));
+ mDevice.mLayers.emplace(std::make_pair(layer->getId(), layer));
+ *outLayerId = layer->getId();
+ ALOGV("[%" PRIu64 "] created layer %" PRIu64, mId, *outLayerId);
+ markGeometryChanged();
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::destroyLayer(hwc2_layer_t layerId) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ const auto mapLayer = mDevice.mLayers.find(layerId);
+ if (mapLayer == mDevice.mLayers.end()) {
+ ALOGV("[%" PRIu64 "] destroyLayer(%" PRIu64 ") failed: no such layer",
+ mId, layerId);
+ return Error::BadLayer;
+ }
+ const auto layer = mapLayer->second;
+ mDevice.mLayers.erase(mapLayer);
+ const auto zRange = mLayers.equal_range(layer);
+ for (auto current = zRange.first; current != zRange.second; ++current) {
+ if (**current == *layer) {
+ current = mLayers.erase(current);
+ break;
+ }
+ }
+ ALOGV("[%" PRIu64 "] destroyed layer %" PRIu64, mId, layerId);
+ markGeometryChanged();
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getActiveConfig(hwc2_config_t* outConfig) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (!mActiveConfig) {
+ ALOGV("[%" PRIu64 "] getActiveConfig --> %s", mId,
+ to_string(Error::BadConfig).c_str());
+ return Error::BadConfig;
+ }
+ auto configId = mActiveConfig->getId();
+ ALOGV("[%" PRIu64 "] getActiveConfig --> %u", mId, configId);
+ *outConfig = configId;
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getAttribute(hwc2_config_t configId,
+ Attribute attribute, int32_t* outValue) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) {
+ ALOGV("[%" PRIu64 "] getAttribute failed: bad config (%u)", mId,
+ configId);
+ return Error::BadConfig;
+ }
+ *outValue = mConfigs[configId]->getAttribute(attribute);
+ ALOGV("[%" PRIu64 "] getAttribute(%u, %s) --> %d", mId, configId,
+ to_string(attribute).c_str(), *outValue);
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getChangedCompositionTypes(
+ uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outTypes) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (!mChanges) {
+ ALOGE("[%" PRIu64 "] getChangedCompositionTypes failed: not validated",
+ mId);
+ return Error::NotValidated;
+ }
+
+ if ((outLayers == nullptr) || (outTypes == nullptr)) {
+ *outNumElements = mChanges->getTypeChanges().size();
+ return Error::None;
+ }
+
+ uint32_t numWritten = 0;
+ for (const auto& element : mChanges->getTypeChanges()) {
+ if (numWritten == *outNumElements) {
+ break;
+ }
+ auto layerId = element.first;
+ auto intType = static_cast<int32_t>(element.second);
+ ALOGV("Adding %" PRIu64 " %s", layerId,
+ to_string(element.second).c_str());
+ outLayers[numWritten] = layerId;
+ outTypes[numWritten] = intType;
+ ++numWritten;
+ }
+ *outNumElements = numWritten;
+
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getColorModes(uint32_t* outNumModes,
+ int32_t* outModes) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (!outModes) {
+ *outNumModes = mColorModes.size();
+ return Error::None;
+ }
+ uint32_t numModes = std::min(*outNumModes,
+ static_cast<uint32_t>(mColorModes.size()));
+ std::copy_n(mColorModes.cbegin(), numModes, outModes);
+ *outNumModes = numModes;
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getConfigs(uint32_t* outNumConfigs,
+ hwc2_config_t* outConfigs) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (!outConfigs) {
+ *outNumConfigs = mConfigs.size();
+ return Error::None;
+ }
+ uint32_t numWritten = 0;
+ for (const auto& config : mConfigs) {
+ if (numWritten == *outNumConfigs) {
+ break;
+ }
+ outConfigs[numWritten] = config->getId();
+ ++numWritten;
+ }
+ *outNumConfigs = numWritten;
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getDozeSupport(int32_t* outSupport) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (mDevice.mHwc1MinorVersion < 4 || mHwc1Id != 0) {
+ *outSupport = 0;
+ } else {
+ *outSupport = 1;
+ }
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getHdrCapabilities(uint32_t* outNumTypes,
+ int32_t* /*outTypes*/, float* /*outMaxLuminance*/,
+ float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/) {
+ // This isn't supported on HWC1, so per the HWC2 header, return numTypes = 0
+ *outNumTypes = 0;
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getName(uint32_t* outSize, char* outName) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (!outName) {
+ *outSize = mName.size();
+ return Error::None;
+ }
+ auto numCopied = mName.copy(outName, *outSize);
+ *outSize = numCopied;
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getReleaseFences(uint32_t* outNumElements,
+ hwc2_layer_t* outLayers, int32_t* outFences) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ uint32_t numWritten = 0;
+ bool outputsNonNull = (outLayers != nullptr) && (outFences != nullptr);
+ for (const auto& layer : mLayers) {
+ if (outputsNonNull && (numWritten == *outNumElements)) {
+ break;
+ }
+
+ auto releaseFence = layer->getReleaseFence();
+ if (releaseFence != MiniFence::NO_FENCE) {
+ if (outputsNonNull) {
+ outLayers[numWritten] = layer->getId();
+ outFences[numWritten] = releaseFence->dup();
+ }
+ ++numWritten;
+ }
+ }
+ *outNumElements = numWritten;
+
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getRequests(int32_t* outDisplayRequests,
+ uint32_t* outNumElements, hwc2_layer_t* outLayers,
+ int32_t* outLayerRequests) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (!mChanges) {
+ return Error::NotValidated;
+ }
+
+ if (outLayers == nullptr || outLayerRequests == nullptr) {
+ *outNumElements = mChanges->getNumLayerRequests();
+ return Error::None;
+ }
+
+ // Display requests (HWC2::DisplayRequest) are not supported by hwc1:
+ // A hwc1 has always zero requests for the client.
+ *outDisplayRequests = 0;
+
+ uint32_t numWritten = 0;
+ for (const auto& request : mChanges->getLayerRequests()) {
+ if (numWritten == *outNumElements) {
+ break;
+ }
+ outLayers[numWritten] = request.first;
+ outLayerRequests[numWritten] = static_cast<int32_t>(request.second);
+ ++numWritten;
+ }
+
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getType(int32_t* outType) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ *outType = static_cast<int32_t>(mType);
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::present(int32_t* outRetireFence) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (mChanges) {
+ Error error = mDevice.setAllDisplays();
+ if (error != Error::None) {
+ ALOGE("[%" PRIu64 "] present: setAllDisplaysFailed (%s)", mId,
+ to_string(error).c_str());
+ return error;
+ }
+ }
+
+ *outRetireFence = mRetireFence.get()->dup();
+ ALOGV("[%" PRIu64 "] present returning retire fence %d", mId,
+ *outRetireFence);
+
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setActiveConfig(hwc2_config_t configId) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ auto config = getConfig(configId);
+ if (!config) {
+ return Error::BadConfig;
+ }
+ if (config == mActiveConfig) {
+ return Error::None;
+ }
+
+ if (mDevice.mHwc1MinorVersion >= 4) {
+ uint32_t hwc1Id = 0;
+ auto error = config->getHwc1IdForColorMode(mActiveColorMode, &hwc1Id);
+ if (error != Error::None) {
+ return error;
+ }
+
+ int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device,
+ mHwc1Id, static_cast<int>(hwc1Id));
+ if (intError != 0) {
+ ALOGE("setActiveConfig: Failed to set active config on HWC1 (%d)",
+ intError);
+ return Error::BadConfig;
+ }
+ mActiveConfig = config;
+ }
+
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setClientTarget(buffer_handle_t target,
+ int32_t acquireFence, int32_t /*dataspace*/, hwc_region_t /*damage*/) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ ALOGV("[%" PRIu64 "] setClientTarget(%p, %d)", mId, target, acquireFence);
+ mClientTarget.setBuffer(target);
+ mClientTarget.setFence(acquireFence);
+ // dataspace and damage can't be used by HWC1, so ignore them
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setColorMode(android_color_mode_t mode) {
+ std::unique_lock<std::recursive_mutex> lock (mStateMutex);
+
+ ALOGV("[%" PRIu64 "] setColorMode(%d)", mId, mode);
+
+ if (mode == mActiveColorMode) {
+ return Error::None;
+ }
+ if (mColorModes.count(mode) == 0) {
+ ALOGE("[%" PRIu64 "] Mode %d not found in mColorModes", mId, mode);
+ return Error::Unsupported;
+ }
+
+ uint32_t hwc1Config = 0;
+ auto error = mActiveConfig->getHwc1IdForColorMode(mode, &hwc1Config);
+ if (error != Error::None) {
+ return error;
+ }
+
+ ALOGV("[%" PRIu64 "] Setting HWC1 config %u", mId, hwc1Config);
+ int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device,
+ mHwc1Id, hwc1Config);
+ if (intError != 0) {
+ ALOGE("[%" PRIu64 "] Failed to set HWC1 config (%d)", mId, intError);
+ return Error::Unsupported;
+ }
+
+ mActiveColorMode = mode;
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setColorTransform(android_color_transform_t hint) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ ALOGV("%" PRIu64 "] setColorTransform(%d)", mId,
+ static_cast<int32_t>(hint));
+ mHasColorTransform = (hint != HAL_COLOR_TRANSFORM_IDENTITY);
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setOutputBuffer(buffer_handle_t buffer,
+ int32_t releaseFence) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ ALOGV("[%" PRIu64 "] setOutputBuffer(%p, %d)", mId, buffer, releaseFence);
+ mOutputBuffer.setBuffer(buffer);
+ mOutputBuffer.setFence(releaseFence);
+ return Error::None;
+}
+
+static bool isValid(PowerMode mode) {
+ switch (mode) {
+ case PowerMode::Off: // Fall-through
+ case PowerMode::DozeSuspend: // Fall-through
+ case PowerMode::Doze: // Fall-through
+ case PowerMode::On: return true;
+ }
+}
+
+static int getHwc1PowerMode(PowerMode mode) {
+ switch (mode) {
+ case PowerMode::Off: return HWC_POWER_MODE_OFF;
+ case PowerMode::DozeSuspend: return HWC_POWER_MODE_DOZE_SUSPEND;
+ case PowerMode::Doze: return HWC_POWER_MODE_DOZE;
+ case PowerMode::On: return HWC_POWER_MODE_NORMAL;
+ }
+}
+
+Error HWC2On1Adapter::Display::setPowerMode(PowerMode mode) {
+ if (!isValid(mode)) {
+ return Error::BadParameter;
+ }
+ if (mode == mPowerMode) {
+ return Error::None;
+ }
+
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ int error = 0;
+ if (mDevice.mHwc1MinorVersion < 4) {
+ error = mDevice.mHwc1Device->blank(mDevice.mHwc1Device, mHwc1Id,
+ mode == PowerMode::Off);
+ } else {
+ error = mDevice.mHwc1Device->setPowerMode(mDevice.mHwc1Device,
+ mHwc1Id, getHwc1PowerMode(mode));
+ }
+ ALOGE_IF(error != 0, "setPowerMode: Failed to set power mode on HWC1 (%d)",
+ error);
+
+ ALOGV("[%" PRIu64 "] setPowerMode(%s)", mId, to_string(mode).c_str());
+ mPowerMode = mode;
+ return Error::None;
+}
+
+static bool isValid(Vsync enable) {
+ switch (enable) {
+ case Vsync::Enable: // Fall-through
+ case Vsync::Disable: return true;
+ case Vsync::Invalid: return false;
+ }
+}
+
+Error HWC2On1Adapter::Display::setVsyncEnabled(Vsync enable) {
+ if (!isValid(enable)) {
+ return Error::BadParameter;
+ }
+ if (enable == mVsyncEnabled) {
+ return Error::None;
+ }
+
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ int error = mDevice.mHwc1Device->eventControl(mDevice.mHwc1Device,
+ mHwc1Id, HWC_EVENT_VSYNC, enable == Vsync::Enable);
+ ALOGE_IF(error != 0, "setVsyncEnabled: Failed to set vsync on HWC1 (%d)",
+ error);
+
+ mVsyncEnabled = enable;
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::validate(uint32_t* outNumTypes,
+ uint32_t* outNumRequests) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (!mChanges) {
+ if (!mDevice.prepareAllDisplays()) {
+ return Error::BadDisplay;
+ }
+ } else {
+ ALOGE("Validate was called more than once!");
+ }
+
+ *outNumTypes = mChanges->getNumTypes();
+ *outNumRequests = mChanges->getNumLayerRequests();
+ ALOGV("[%" PRIu64 "] validate --> %u types, %u requests", mId, *outNumTypes,
+ *outNumRequests);
+ for (auto request : mChanges->getTypeChanges()) {
+ ALOGV("Layer %" PRIu64 " --> %s", request.first,
+ to_string(request.second).c_str());
+ }
+ return *outNumTypes > 0 ? Error::HasChanges : Error::None;
+}
+
+Error HWC2On1Adapter::Display::updateLayerZ(hwc2_layer_t layerId, uint32_t z) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ const auto mapLayer = mDevice.mLayers.find(layerId);
+ if (mapLayer == mDevice.mLayers.end()) {
+ ALOGE("[%" PRIu64 "] updateLayerZ failed to find layer", mId);
+ return Error::BadLayer;
+ }
+
+ const auto layer = mapLayer->second;
+ const auto zRange = mLayers.equal_range(layer);
+ bool layerOnDisplay = false;
+ for (auto current = zRange.first; current != zRange.second; ++current) {
+ if (**current == *layer) {
+ if ((*current)->getZ() == z) {
+ // Don't change anything if the Z hasn't changed
+ return Error::None;
+ }
+ current = mLayers.erase(current);
+ layerOnDisplay = true;
+ break;
+ }
+ }
+
+ if (!layerOnDisplay) {
+ ALOGE("[%" PRIu64 "] updateLayerZ failed to find layer on display",
+ mId);
+ return Error::BadLayer;
+ }
+
+ layer->setZ(z);
+ mLayers.emplace(std::move(layer));
+ markGeometryChanged();
+
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getClientTargetSupport(uint32_t width, uint32_t height,
+ int32_t format, int32_t dataspace){
+ if (mActiveConfig == nullptr) {
+ return Error::Unsupported;
+ }
+
+ if (width == mActiveConfig->getAttribute(Attribute::Width) &&
+ height == mActiveConfig->getAttribute(Attribute::Height) &&
+ format == HAL_PIXEL_FORMAT_RGBA_8888 &&
+ dataspace == HAL_DATASPACE_UNKNOWN) {
+ return Error::None;
+ }
+
+ return Error::Unsupported;
+}
+
+static constexpr uint32_t ATTRIBUTES_WITH_COLOR[] = {
+ HWC_DISPLAY_VSYNC_PERIOD,
+ HWC_DISPLAY_WIDTH,
+ HWC_DISPLAY_HEIGHT,
+ HWC_DISPLAY_DPI_X,
+ HWC_DISPLAY_DPI_Y,
+ HWC_DISPLAY_COLOR_TRANSFORM,
+ HWC_DISPLAY_NO_ATTRIBUTE,
+};
+
+static constexpr uint32_t ATTRIBUTES_WITHOUT_COLOR[] = {
+ HWC_DISPLAY_VSYNC_PERIOD,
+ HWC_DISPLAY_WIDTH,
+ HWC_DISPLAY_HEIGHT,
+ HWC_DISPLAY_DPI_X,
+ HWC_DISPLAY_DPI_Y,
+ HWC_DISPLAY_NO_ATTRIBUTE,
+};
+
+static constexpr size_t NUM_ATTRIBUTES_WITH_COLOR =
+ sizeof(ATTRIBUTES_WITH_COLOR) / sizeof(uint32_t);
+static_assert(sizeof(ATTRIBUTES_WITH_COLOR) > sizeof(ATTRIBUTES_WITHOUT_COLOR),
+ "Attribute tables have unexpected sizes");
+
+static constexpr uint32_t ATTRIBUTE_MAP_WITH_COLOR[] = {
+ 6, // HWC_DISPLAY_NO_ATTRIBUTE = 0
+ 0, // HWC_DISPLAY_VSYNC_PERIOD = 1,
+ 1, // HWC_DISPLAY_WIDTH = 2,
+ 2, // HWC_DISPLAY_HEIGHT = 3,
+ 3, // HWC_DISPLAY_DPI_X = 4,
+ 4, // HWC_DISPLAY_DPI_Y = 5,
+ 5, // HWC_DISPLAY_COLOR_TRANSFORM = 6,
+};
+
+static constexpr uint32_t ATTRIBUTE_MAP_WITHOUT_COLOR[] = {
+ 5, // HWC_DISPLAY_NO_ATTRIBUTE = 0
+ 0, // HWC_DISPLAY_VSYNC_PERIOD = 1,
+ 1, // HWC_DISPLAY_WIDTH = 2,
+ 2, // HWC_DISPLAY_HEIGHT = 3,
+ 3, // HWC_DISPLAY_DPI_X = 4,
+ 4, // HWC_DISPLAY_DPI_Y = 5,
+};
+
+template <uint32_t attribute>
+static constexpr bool attributesMatch()
+{
+ bool match = (attribute ==
+ ATTRIBUTES_WITH_COLOR[ATTRIBUTE_MAP_WITH_COLOR[attribute]]);
+ if (attribute == HWC_DISPLAY_COLOR_TRANSFORM) {
+ return match;
+ }
+
+ return match && (attribute ==
+ ATTRIBUTES_WITHOUT_COLOR[ATTRIBUTE_MAP_WITHOUT_COLOR[attribute]]);
+}
+static_assert(attributesMatch<HWC_DISPLAY_VSYNC_PERIOD>(),
+ "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_WIDTH>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_HEIGHT>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_DPI_X>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_DPI_Y>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_COLOR_TRANSFORM>(),
+ "Tables out of sync");
+
+void HWC2On1Adapter::Display::populateConfigs() {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ ALOGV("[%" PRIu64 "] populateConfigs", mId);
+
+ if (mHwc1Id == -1) {
+ ALOGE("populateConfigs: HWC1 ID not set");
+ return;
+ }
+
+ const size_t MAX_NUM_CONFIGS = 128;
+ uint32_t configs[MAX_NUM_CONFIGS] = {};
+ size_t numConfigs = MAX_NUM_CONFIGS;
+ mDevice.mHwc1Device->getDisplayConfigs(mDevice.mHwc1Device, mHwc1Id,
+ configs, &numConfigs);
+
+ for (size_t c = 0; c < numConfigs; ++c) {
+ uint32_t hwc1ConfigId = configs[c];
+ auto newConfig = std::make_shared<Config>(*this);
+
+ int32_t values[NUM_ATTRIBUTES_WITH_COLOR] = {};
+ bool hasColor = true;
+ auto result = mDevice.mHwc1Device->getDisplayAttributes(
+ mDevice.mHwc1Device, mHwc1Id, hwc1ConfigId,
+ ATTRIBUTES_WITH_COLOR, values);
+ if (result != 0) {
+ mDevice.mHwc1Device->getDisplayAttributes(mDevice.mHwc1Device,
+ mHwc1Id, hwc1ConfigId, ATTRIBUTES_WITHOUT_COLOR, values);
+ hasColor = false;
+ }
+
+ auto attributeMap = hasColor ?
+ ATTRIBUTE_MAP_WITH_COLOR : ATTRIBUTE_MAP_WITHOUT_COLOR;
+
+ newConfig->setAttribute(Attribute::VsyncPeriod,
+ values[attributeMap[HWC_DISPLAY_VSYNC_PERIOD]]);
+ newConfig->setAttribute(Attribute::Width,
+ values[attributeMap[HWC_DISPLAY_WIDTH]]);
+ newConfig->setAttribute(Attribute::Height,
+ values[attributeMap[HWC_DISPLAY_HEIGHT]]);
+ newConfig->setAttribute(Attribute::DpiX,
+ values[attributeMap[HWC_DISPLAY_DPI_X]]);
+ newConfig->setAttribute(Attribute::DpiY,
+ values[attributeMap[HWC_DISPLAY_DPI_Y]]);
+ if (hasColor) {
+ // In HWC1, color modes are referred to as color transforms. To avoid confusion with
+ // the HWC2 concept of color transforms, we internally refer to them as color modes for
+ // both HWC1 and 2.
+ newConfig->setAttribute(ColorMode,
+ values[attributeMap[HWC_DISPLAY_COLOR_TRANSFORM]]);
+ }
+
+ // We can only do this after attempting to read the color mode
+ newConfig->setHwc1Id(hwc1ConfigId);
+
+ for (auto& existingConfig : mConfigs) {
+ if (existingConfig->merge(*newConfig)) {
+ ALOGV("Merged config %d with existing config %u: %s",
+ hwc1ConfigId, existingConfig->getId(),
+ existingConfig->toString().c_str());
+ newConfig.reset();
+ break;
+ }
+ }
+
+ // If it wasn't merged with any existing config, add it to the end
+ if (newConfig) {
+ newConfig->setId(static_cast<hwc2_config_t>(mConfigs.size()));
+ ALOGV("Found new config %u: %s", newConfig->getId(),
+ newConfig->toString().c_str());
+ mConfigs.emplace_back(std::move(newConfig));
+ }
+ }
+
+ initializeActiveConfig();
+ populateColorModes();
+}
+
+void HWC2On1Adapter::Display::populateConfigs(uint32_t width, uint32_t height) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ mConfigs.emplace_back(std::make_shared<Config>(*this));
+ auto& config = mConfigs[0];
+
+ config->setAttribute(Attribute::Width, static_cast<int32_t>(width));
+ config->setAttribute(Attribute::Height, static_cast<int32_t>(height));
+ config->setHwc1Id(0);
+ config->setId(0);
+ mActiveConfig = config;
+}
+
+bool HWC2On1Adapter::Display::prepare() {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ // Only prepare display contents for displays HWC1 knows about
+ if (mHwc1Id == -1) {
+ return true;
+ }
+
+ // It doesn't make sense to prepare a display for which there is no active
+ // config, so return early
+ if (!mActiveConfig) {
+ ALOGE("[%" PRIu64 "] Attempted to prepare, but no config active", mId);
+ return false;
+ }
+
+ allocateRequestedContents();
+ assignHwc1LayerIds();
+
+ mHwc1RequestedContents->retireFenceFd = -1;
+ mHwc1RequestedContents->flags = 0;
+ if (mGeometryChanged) {
+ mHwc1RequestedContents->flags |= HWC_GEOMETRY_CHANGED;
+ }
+ mHwc1RequestedContents->outbuf = mOutputBuffer.getBuffer();
+ mHwc1RequestedContents->outbufAcquireFenceFd = mOutputBuffer.getFence();
+
+ // +1 is for framebuffer target layer.
+ mHwc1RequestedContents->numHwLayers = mLayers.size() + 1;
+ for (auto& layer : mLayers) {
+ auto& hwc1Layer = mHwc1RequestedContents->hwLayers[layer->getHwc1Id()];
+ hwc1Layer.releaseFenceFd = -1;
+ hwc1Layer.acquireFenceFd = -1;
+ ALOGV("Applying states for layer %" PRIu64 " ", layer->getId());
+ layer->applyState(hwc1Layer);
+ }
+
+ prepareFramebufferTarget();
+
+ resetGeometryMarker();
+
+ return true;
+}
+
+void HWC2On1Adapter::Display::generateChanges() {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ mChanges.reset(new Changes);
+
+ size_t numLayers = mHwc1RequestedContents->numHwLayers;
+ for (size_t hwc1Id = 0; hwc1Id < numLayers; ++hwc1Id) {
+ const auto& receivedLayer = mHwc1RequestedContents->hwLayers[hwc1Id];
+ if (mHwc1LayerMap.count(hwc1Id) == 0) {
+ ALOGE_IF(receivedLayer.compositionType != HWC_FRAMEBUFFER_TARGET,
+ "generateChanges: HWC1 layer %zd doesn't have a"
+ " matching HWC2 layer, and isn't the framebuffer target",
+ hwc1Id);
+ continue;
+ }
+
+ Layer& layer = *mHwc1LayerMap[hwc1Id];
+ updateTypeChanges(receivedLayer, layer);
+ updateLayerRequests(receivedLayer, layer);
+ }
+}
+
+bool HWC2On1Adapter::Display::hasChanges() const {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+ return mChanges != nullptr;
+}
+
+Error HWC2On1Adapter::Display::set(hwc_display_contents_1& hwcContents) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (!mChanges || (mChanges->getNumTypes() > 0)) {
+ ALOGE("[%" PRIu64 "] set failed: not validated", mId);
+ return Error::NotValidated;
+ }
+
+ // Set up the client/framebuffer target
+ auto numLayers = hwcContents.numHwLayers;
+
+ // Close acquire fences on FRAMEBUFFER layers, since they will not be used
+ // by HWC
+ for (size_t l = 0; l < numLayers - 1; ++l) {
+ auto& layer = hwcContents.hwLayers[l];
+ if (layer.compositionType == HWC_FRAMEBUFFER) {
+ ALOGV("Closing fence %d for layer %zd", layer.acquireFenceFd, l);
+ close(layer.acquireFenceFd);
+ layer.acquireFenceFd = -1;
+ }
+ }
+
+ auto& clientTargetLayer = hwcContents.hwLayers[numLayers - 1];
+ if (clientTargetLayer.compositionType == HWC_FRAMEBUFFER_TARGET) {
+ clientTargetLayer.handle = mClientTarget.getBuffer();
+ clientTargetLayer.acquireFenceFd = mClientTarget.getFence();
+ } else {
+ ALOGE("[%" PRIu64 "] set: last HWC layer wasn't FRAMEBUFFER_TARGET",
+ mId);
+ }
+
+ mChanges.reset();
+
+ return Error::None;
+}
+
+void HWC2On1Adapter::Display::addRetireFence(int fenceFd) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+ mRetireFence.add(fenceFd);
+}
+
+void HWC2On1Adapter::Display::addReleaseFences(
+ const hwc_display_contents_1_t& hwcContents) {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ size_t numLayers = hwcContents.numHwLayers;
+ for (size_t hwc1Id = 0; hwc1Id < numLayers; ++hwc1Id) {
+ const auto& receivedLayer = hwcContents.hwLayers[hwc1Id];
+ if (mHwc1LayerMap.count(hwc1Id) == 0) {
+ if (receivedLayer.compositionType != HWC_FRAMEBUFFER_TARGET) {
+ ALOGE("addReleaseFences: HWC1 layer %zd doesn't have a"
+ " matching HWC2 layer, and isn't the framebuffer"
+ " target", hwc1Id);
+ }
+ // Close the framebuffer target release fence since we will use the
+ // display retire fence instead
+ if (receivedLayer.releaseFenceFd != -1) {
+ close(receivedLayer.releaseFenceFd);
+ }
+ continue;
+ }
+
+ Layer& layer = *mHwc1LayerMap[hwc1Id];
+ ALOGV("Adding release fence %d to layer %" PRIu64,
+ receivedLayer.releaseFenceFd, layer.getId());
+ layer.addReleaseFence(receivedLayer.releaseFenceFd);
+ }
+}
+
+bool HWC2On1Adapter::Display::hasColorTransform() const {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+ return mHasColorTransform;
+}
+
+static std::string hwc1CompositionString(int32_t type) {
+ switch (type) {
+ case HWC_FRAMEBUFFER: return "Framebuffer";
+ case HWC_OVERLAY: return "Overlay";
+ case HWC_BACKGROUND: return "Background";
+ case HWC_FRAMEBUFFER_TARGET: return "FramebufferTarget";
+ case HWC_SIDEBAND: return "Sideband";
+ case HWC_CURSOR_OVERLAY: return "CursorOverlay";
+ default:
+ return std::string("Unknown (") + std::to_string(type) + ")";
+ }
+}
+
+static std::string hwc1TransformString(int32_t transform) {
+ switch (transform) {
+ case 0: return "None";
+ case HWC_TRANSFORM_FLIP_H: return "FlipH";
+ case HWC_TRANSFORM_FLIP_V: return "FlipV";
+ case HWC_TRANSFORM_ROT_90: return "Rotate90";
+ case HWC_TRANSFORM_ROT_180: return "Rotate180";
+ case HWC_TRANSFORM_ROT_270: return "Rotate270";
+ case HWC_TRANSFORM_FLIP_H_ROT_90: return "FlipHRotate90";
+ case HWC_TRANSFORM_FLIP_V_ROT_90: return "FlipVRotate90";
+ default:
+ return std::string("Unknown (") + std::to_string(transform) + ")";
+ }
+}
+
+static std::string hwc1BlendModeString(int32_t mode) {
+ switch (mode) {
+ case HWC_BLENDING_NONE: return "None";
+ case HWC_BLENDING_PREMULT: return "Premultiplied";
+ case HWC_BLENDING_COVERAGE: return "Coverage";
+ default:
+ return std::string("Unknown (") + std::to_string(mode) + ")";
+ }
+}
+
+static std::string rectString(hwc_rect_t rect) {
+ std::stringstream output;
+ output << "[" << rect.left << ", " << rect.top << ", ";
+ output << rect.right << ", " << rect.bottom << "]";
+ return output.str();
+}
+
+static std::string approximateFloatString(float f) {
+ if (static_cast<int32_t>(f) == f) {
+ return std::to_string(static_cast<int32_t>(f));
+ }
+ int32_t truncated = static_cast<int32_t>(f * 10);
+ bool approximate = (static_cast<float>(truncated) != f * 10);
+ const size_t BUFFER_SIZE = 32;
+ char buffer[BUFFER_SIZE] = {};
+ auto bytesWritten = snprintf(buffer, BUFFER_SIZE,
+ "%s%.1f", approximate ? "~" : "", f);
+ return std::string(buffer, bytesWritten);
+}
+
+static std::string frectString(hwc_frect_t frect) {
+ std::stringstream output;
+ output << "[" << approximateFloatString(frect.left) << ", ";
+ output << approximateFloatString(frect.top) << ", ";
+ output << approximateFloatString(frect.right) << ", ";
+ output << approximateFloatString(frect.bottom) << "]";
+ return output.str();
+}
+
+static std::string colorString(hwc_color_t color) {
+ std::stringstream output;
+ output << "RGBA [";
+ output << static_cast<int32_t>(color.r) << ", ";
+ output << static_cast<int32_t>(color.g) << ", ";
+ output << static_cast<int32_t>(color.b) << ", ";
+ output << static_cast<int32_t>(color.a) << "]";
+ return output.str();
+}
+
+static std::string alphaString(float f) {
+ const size_t BUFFER_SIZE = 8;
+ char buffer[BUFFER_SIZE] = {};
+ auto bytesWritten = snprintf(buffer, BUFFER_SIZE, "%.3f", f);
+ return std::string(buffer, bytesWritten);
+}
+
+static std::string to_string(const hwc_layer_1_t& hwcLayer,
+ int32_t hwc1MinorVersion) {
+ const char* fill = " ";
+
+ std::stringstream output;
+
+ output << " Composition: " <<
+ hwc1CompositionString(hwcLayer.compositionType);
+
+ if (hwcLayer.compositionType == HWC_BACKGROUND) {
+ output << " Color: " << colorString(hwcLayer.backgroundColor) << '\n';
+ } else if (hwcLayer.compositionType == HWC_SIDEBAND) {
+ output << " Stream: " << hwcLayer.sidebandStream << '\n';
+ } else {
+ output << " Buffer: " << hwcLayer.handle << "/" <<
+ hwcLayer.acquireFenceFd << '\n';
+ }
+
+ output << fill << "Display frame: " << rectString(hwcLayer.displayFrame) <<
+ '\n';
+
+ output << fill << "Source crop: ";
+ if (hwc1MinorVersion >= 3) {
+ output << frectString(hwcLayer.sourceCropf) << '\n';
+ } else {
+ output << rectString(hwcLayer.sourceCropi) << '\n';
+ }
+
+ output << fill << "Transform: " << hwc1TransformString(hwcLayer.transform);
+ output << " Blend mode: " << hwc1BlendModeString(hwcLayer.blending);
+ if (hwcLayer.planeAlpha != 0xFF) {
+ output << " Alpha: " << alphaString(hwcLayer.planeAlpha / 255.0f);
+ }
+ output << '\n';
+
+ if (hwcLayer.hints != 0) {
+ output << fill << "Hints:";
+ if ((hwcLayer.hints & HWC_HINT_TRIPLE_BUFFER) != 0) {
+ output << " TripleBuffer";
+ }
+ if ((hwcLayer.hints & HWC_HINT_CLEAR_FB) != 0) {
+ output << " ClearFB";
+ }
+ output << '\n';
+ }
+
+ if (hwcLayer.flags != 0) {
+ output << fill << "Flags:";
+ if ((hwcLayer.flags & HWC_SKIP_LAYER) != 0) {
+ output << " SkipLayer";
+ }
+ if ((hwcLayer.flags & HWC_IS_CURSOR_LAYER) != 0) {
+ output << " IsCursorLayer";
+ }
+ output << '\n';
+ }
+
+ return output.str();
+}
+
+static std::string to_string(const hwc_display_contents_1_t& hwcContents,
+ int32_t hwc1MinorVersion) {
+ const char* fill = " ";
+
+ std::stringstream output;
+ output << fill << "Geometry changed: " <<
+ ((hwcContents.flags & HWC_GEOMETRY_CHANGED) != 0 ? "Y\n" : "N\n");
+
+ output << fill << hwcContents.numHwLayers << " Layer" <<
+ ((hwcContents.numHwLayers == 1) ? "\n" : "s\n");
+ for (size_t layer = 0; layer < hwcContents.numHwLayers; ++layer) {
+ output << fill << " Layer " << layer;
+ output << to_string(hwcContents.hwLayers[layer], hwc1MinorVersion);
+ }
+
+ if (hwcContents.outbuf != nullptr) {
+ output << fill << "Output buffer: " << hwcContents.outbuf << "/" <<
+ hwcContents.outbufAcquireFenceFd << '\n';
+ }
+
+ return output.str();
+}
+
+std::string HWC2On1Adapter::Display::dump() const {
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ std::stringstream output;
+
+ output << " Display " << mId << ": ";
+ output << to_string(mType) << " ";
+ output << "HWC1 ID: " << mHwc1Id << " ";
+ output << "Power mode: " << to_string(mPowerMode) << " ";
+ output << "Vsync: " << to_string(mVsyncEnabled) << '\n';
+
+ output << " Color modes [active]:";
+ for (const auto& mode : mColorModes) {
+ if (mode == mActiveColorMode) {
+ output << " [" << mode << ']';
+ } else {
+ output << " " << mode;
+ }
+ }
+ output << '\n';
+
+ output << " " << mConfigs.size() << " Config" <<
+ (mConfigs.size() == 1 ? "" : "s") << " (* active)\n";
+ for (const auto& config : mConfigs) {
+ output << (config == mActiveConfig ? " * " : " ");
+ output << config->toString(true) << '\n';
+ }
+
+ output << " " << mLayers.size() << " Layer" <<
+ (mLayers.size() == 1 ? "" : "s") << '\n';
+ for (const auto& layer : mLayers) {
+ output << layer->dump();
+ }
+
+ output << " Client target: " << mClientTarget.getBuffer() << '\n';
+
+ if (mOutputBuffer.getBuffer() != nullptr) {
+ output << " Output buffer: " << mOutputBuffer.getBuffer() << '\n';
+ }
+
+ if (mHwc1RequestedContents) {
+ output << " Last requested HWC1 state\n";
+ output << to_string(*mHwc1RequestedContents, mDevice.mHwc1MinorVersion);
+ }
+
+ return output.str();
+}
+
+hwc_rect_t* HWC2On1Adapter::Display::GetRects(size_t numRects) {
+ if (numRects == 0) {
+ return nullptr;
+ }
+
+ if (numRects > mNumAvailableRects) {
+ // This should NEVER happen since we calculated how many rects the
+ // display would need.
+ ALOGE("Rect allocation failure! SF is likely to crash soon!");
+ return nullptr;
+
+ }
+ hwc_rect_t* rects = mNextAvailableRect;
+ mNextAvailableRect += numRects;
+ mNumAvailableRects -= numRects;
+ return rects;
+}
+
+hwc_display_contents_1* HWC2On1Adapter::Display::getDisplayContents() {
+ return mHwc1RequestedContents.get();
+}
+
+void HWC2On1Adapter::Display::Config::setAttribute(HWC2::Attribute attribute,
+ int32_t value) {
+ mAttributes[attribute] = value;
+}
+
+int32_t HWC2On1Adapter::Display::Config::getAttribute(Attribute attribute) const {
+ if (mAttributes.count(attribute) == 0) {
+ return -1;
+ }
+ return mAttributes.at(attribute);
+}
+
+void HWC2On1Adapter::Display::Config::setHwc1Id(uint32_t id) {
+ android_color_mode_t colorMode = static_cast<android_color_mode_t>(getAttribute(ColorMode));
+ mHwc1Ids.emplace(colorMode, id);
+}
+
+bool HWC2On1Adapter::Display::Config::hasHwc1Id(uint32_t id) const {
+ for (const auto& idPair : mHwc1Ids) {
+ if (id == idPair.second) {
+ return true;
+ }
+ }
+ return false;
+}
+
+Error HWC2On1Adapter::Display::Config::getColorModeForHwc1Id(
+ uint32_t id, android_color_mode_t* outMode) const {
+ for (const auto& idPair : mHwc1Ids) {
+ if (id == idPair.second) {
+ *outMode = idPair.first;
+ return Error::None;
+ }
+ }
+ ALOGE("Unable to find color mode for HWC ID %" PRIu32 " on config %u", id, mId);
+ return Error::BadParameter;
+}
+
+Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(android_color_mode_t mode,
+ uint32_t* outId) const {
+ for (const auto& idPair : mHwc1Ids) {
+ if (mode == idPair.first) {
+ *outId = idPair.second;
+ return Error::None;
+ }
+ }
+ ALOGE("Unable to find HWC1 ID for color mode %d on config %u", mode, mId);
+ return Error::BadParameter;
+}
+
+bool HWC2On1Adapter::Display::Config::merge(const Config& other) {
+ auto attributes = {HWC2::Attribute::Width, HWC2::Attribute::Height,
+ HWC2::Attribute::VsyncPeriod, HWC2::Attribute::DpiX,
+ HWC2::Attribute::DpiY};
+ for (auto attribute : attributes) {
+ if (getAttribute(attribute) != other.getAttribute(attribute)) {
+ return false;
+ }
+ }
+ android_color_mode_t otherColorMode =
+ static_cast<android_color_mode_t>(other.getAttribute(ColorMode));
+ if (mHwc1Ids.count(otherColorMode) != 0) {
+ ALOGE("Attempted to merge two configs (%u and %u) which appear to be "
+ "identical", mHwc1Ids.at(otherColorMode),
+ other.mHwc1Ids.at(otherColorMode));
+ return false;
+ }
+ mHwc1Ids.emplace(otherColorMode,
+ other.mHwc1Ids.at(otherColorMode));
+ return true;
+}
+
+std::set<android_color_mode_t> HWC2On1Adapter::Display::Config::getColorModes() const {
+ std::set<android_color_mode_t> colorModes;
+ for (const auto& idPair : mHwc1Ids) {
+ colorModes.emplace(idPair.first);
+ }
+ return colorModes;
+}
+
+std::string HWC2On1Adapter::Display::Config::toString(bool splitLine) const {
+ std::string output;
+
+ const size_t BUFFER_SIZE = 100;
+ char buffer[BUFFER_SIZE] = {};
+ auto writtenBytes = snprintf(buffer, BUFFER_SIZE,
+ "%u x %u", mAttributes.at(HWC2::Attribute::Width),
+ mAttributes.at(HWC2::Attribute::Height));
+ output.append(buffer, writtenBytes);
+
+ if (mAttributes.count(HWC2::Attribute::VsyncPeriod) != 0) {
+ std::memset(buffer, 0, BUFFER_SIZE);
+ writtenBytes = snprintf(buffer, BUFFER_SIZE, " @ %.1f Hz",
+ 1e9 / mAttributes.at(HWC2::Attribute::VsyncPeriod));
+ output.append(buffer, writtenBytes);
+ }
+
+ if (mAttributes.count(HWC2::Attribute::DpiX) != 0 &&
+ mAttributes.at(HWC2::Attribute::DpiX) != -1) {
+ std::memset(buffer, 0, BUFFER_SIZE);
+ writtenBytes = snprintf(buffer, BUFFER_SIZE,
+ ", DPI: %.1f x %.1f",
+ mAttributes.at(HWC2::Attribute::DpiX) / 1000.0f,
+ mAttributes.at(HWC2::Attribute::DpiY) / 1000.0f);
+ output.append(buffer, writtenBytes);
+ }
+
+ std::memset(buffer, 0, BUFFER_SIZE);
+ if (splitLine) {
+ writtenBytes = snprintf(buffer, BUFFER_SIZE,
+ "\n HWC1 ID/Color transform:");
+ } else {
+ writtenBytes = snprintf(buffer, BUFFER_SIZE,
+ ", HWC1 ID/Color transform:");
+ }
+ output.append(buffer, writtenBytes);
+
+
+ for (const auto& id : mHwc1Ids) {
+ android_color_mode_t colorMode = id.first;
+ uint32_t hwc1Id = id.second;
+ std::memset(buffer, 0, BUFFER_SIZE);
+ if (colorMode == mDisplay.mActiveColorMode) {
+ writtenBytes = snprintf(buffer, BUFFER_SIZE, " [%u/%d]", hwc1Id,
+ colorMode);
+ } else {
+ writtenBytes = snprintf(buffer, BUFFER_SIZE, " %u/%d", hwc1Id,
+ colorMode);
+ }
+ output.append(buffer, writtenBytes);
+ }
+
+ return output;
+}
+
+std::shared_ptr<const HWC2On1Adapter::Display::Config>
+ HWC2On1Adapter::Display::getConfig(hwc2_config_t configId) const {
+ if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) {
+ return nullptr;
+ }
+ return mConfigs[configId];
+}
+
+void HWC2On1Adapter::Display::populateColorModes() {
+ mColorModes = mConfigs[0]->getColorModes();
+ for (const auto& config : mConfigs) {
+ std::set<android_color_mode_t> intersection;
+ auto configModes = config->getColorModes();
+ std::set_intersection(mColorModes.cbegin(), mColorModes.cend(),
+ configModes.cbegin(), configModes.cend(),
+ std::inserter(intersection, intersection.begin()));
+ std::swap(intersection, mColorModes);
+ }
+}
+
+void HWC2On1Adapter::Display::initializeActiveConfig() {
+ if (mDevice.mHwc1Device->getActiveConfig == nullptr) {
+ ALOGV("getActiveConfig is null, choosing config 0");
+ mActiveConfig = mConfigs[0];
+ mActiveColorMode = HAL_COLOR_MODE_NATIVE;
+ return;
+ }
+
+ auto activeConfig = mDevice.mHwc1Device->getActiveConfig(
+ mDevice.mHwc1Device, mHwc1Id);
+
+ // Some devices startup without an activeConfig:
+ // We need to set one ourselves.
+ if (activeConfig == HWC_ERROR) {
+ ALOGV("There is no active configuration: Picking the first one: 0.");
+ const int defaultIndex = 0;
+ mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, mHwc1Id, defaultIndex);
+ activeConfig = defaultIndex;
+ }
+
+ for (const auto& config : mConfigs) {
+ if (config->hasHwc1Id(activeConfig)) {
+ ALOGE("Setting active config to %d for HWC1 config %u", config->getId(), activeConfig);
+ mActiveConfig = config;
+ if (config->getColorModeForHwc1Id(activeConfig, &mActiveColorMode) != Error::None) {
+ // This should never happen since we checked for the config's presence before
+ // setting it as active.
+ ALOGE("Unable to find color mode for active HWC1 config %d", config->getId());
+ mActiveColorMode = HAL_COLOR_MODE_NATIVE;
+ }
+ break;
+ }
+ }
+ if (!mActiveConfig) {
+ ALOGV("Unable to find active HWC1 config %u, defaulting to "
+ "config 0", activeConfig);
+ mActiveConfig = mConfigs[0];
+ mActiveColorMode = HAL_COLOR_MODE_NATIVE;
+ }
+
+
+
+
+}
+
+void HWC2On1Adapter::Display::allocateRequestedContents() {
+ // What needs to be allocated:
+ // 1 hwc_display_contents_1_t
+ // 1 hwc_layer_1_t for each layer
+ // 1 hwc_rect_t for each layer's surfaceDamage
+ // 1 hwc_rect_t for each layer's visibleRegion
+ // 1 hwc_layer_1_t for the framebuffer
+ // 1 hwc_rect_t for the framebuffer's visibleRegion
+
+ // Count # of surfaceDamage
+ size_t numSurfaceDamages = 0;
+ for (const auto& layer : mLayers) {
+ numSurfaceDamages += layer->getNumSurfaceDamages();
+ }
+
+ // Count # of visibleRegions (start at 1 for mandatory framebuffer target
+ // region)
+ size_t numVisibleRegion = 1;
+ for (const auto& layer : mLayers) {
+ numVisibleRegion += layer->getNumVisibleRegions();
+ }
+
+ size_t numRects = numVisibleRegion + numSurfaceDamages;
+ auto numLayers = mLayers.size() + 1;
+ size_t size = sizeof(hwc_display_contents_1_t) +
+ sizeof(hwc_layer_1_t) * numLayers +
+ sizeof(hwc_rect_t) * numRects;
+ auto contents = static_cast<hwc_display_contents_1_t*>(std::calloc(size, 1));
+ mHwc1RequestedContents.reset(contents);
+ mNextAvailableRect = reinterpret_cast<hwc_rect_t*>(&contents->hwLayers[numLayers]);
+ mNumAvailableRects = numRects;
+}
+
+void HWC2On1Adapter::Display::assignHwc1LayerIds() {
+ mHwc1LayerMap.clear();
+ size_t nextHwc1Id = 0;
+ for (auto& layer : mLayers) {
+ mHwc1LayerMap[nextHwc1Id] = layer;
+ layer->setHwc1Id(nextHwc1Id++);
+ }
+}
+
+void HWC2On1Adapter::Display::updateTypeChanges(const hwc_layer_1_t& hwc1Layer,
+ const Layer& layer) {
+ auto layerId = layer.getId();
+ switch (hwc1Layer.compositionType) {
+ case HWC_FRAMEBUFFER:
+ if (layer.getCompositionType() != Composition::Client) {
+ mChanges->addTypeChange(layerId, Composition::Client);
+ }
+ break;
+ case HWC_OVERLAY:
+ if (layer.getCompositionType() != Composition::Device) {
+ mChanges->addTypeChange(layerId, Composition::Device);
+ }
+ break;
+ case HWC_BACKGROUND:
+ ALOGE_IF(layer.getCompositionType() != Composition::SolidColor,
+ "updateTypeChanges: HWC1 requested BACKGROUND, but HWC2"
+ " wasn't expecting SolidColor");
+ break;
+ case HWC_FRAMEBUFFER_TARGET:
+ // Do nothing, since it shouldn't be modified by HWC1
+ break;
+ case HWC_SIDEBAND:
+ ALOGE_IF(layer.getCompositionType() != Composition::Sideband,
+ "updateTypeChanges: HWC1 requested SIDEBAND, but HWC2"
+ " wasn't expecting Sideband");
+ break;
+ case HWC_CURSOR_OVERLAY:
+ ALOGE_IF(layer.getCompositionType() != Composition::Cursor,
+ "updateTypeChanges: HWC1 requested CURSOR_OVERLAY, but"
+ " HWC2 wasn't expecting Cursor");
+ break;
+ }
+}
+
+void HWC2On1Adapter::Display::updateLayerRequests(
+ const hwc_layer_1_t& hwc1Layer, const Layer& layer) {
+ if ((hwc1Layer.hints & HWC_HINT_CLEAR_FB) != 0) {
+ mChanges->addLayerRequest(layer.getId(),
+ LayerRequest::ClearClientTarget);
+ }
+}
+
+void HWC2On1Adapter::Display::prepareFramebufferTarget() {
+ // We check that mActiveConfig is valid in Display::prepare
+ int32_t width = mActiveConfig->getAttribute(Attribute::Width);
+ int32_t height = mActiveConfig->getAttribute(Attribute::Height);
+
+ auto& hwc1Target = mHwc1RequestedContents->hwLayers[mLayers.size()];
+ hwc1Target.compositionType = HWC_FRAMEBUFFER_TARGET;
+ hwc1Target.releaseFenceFd = -1;
+ hwc1Target.hints = 0;
+ hwc1Target.flags = 0;
+ hwc1Target.transform = 0;
+ hwc1Target.blending = HWC_BLENDING_PREMULT;
+ if (mDevice.getHwc1MinorVersion() < 3) {
+ hwc1Target.sourceCropi = {0, 0, width, height};
+ } else {
+ hwc1Target.sourceCropf = {0.0f, 0.0f, static_cast<float>(width),
+ static_cast<float>(height)};
+ }
+ hwc1Target.displayFrame = {0, 0, width, height};
+ hwc1Target.planeAlpha = 255;
+
+ hwc1Target.visibleRegionScreen.numRects = 1;
+ hwc_rect_t* rects = GetRects(1);
+ rects[0].left = 0;
+ rects[0].top = 0;
+ rects[0].right = width;
+ rects[0].bottom = height;
+ hwc1Target.visibleRegionScreen.rects = rects;
+
+ // We will set this to the correct value in set
+ hwc1Target.acquireFenceFd = -1;
+}
+
+// Layer functions
+
+std::atomic<hwc2_layer_t> HWC2On1Adapter::Layer::sNextId(1);
+
+HWC2On1Adapter::Layer::Layer(Display& display)
+ : mId(sNextId++),
+ mDisplay(display),
+ mBuffer(),
+ mSurfaceDamage(),
+ mBlendMode(BlendMode::None),
+ mColor({0, 0, 0, 0}),
+ mCompositionType(Composition::Invalid),
+ mDisplayFrame({0, 0, -1, -1}),
+ mPlaneAlpha(0.0f),
+ mSidebandStream(nullptr),
+ mSourceCrop({0.0f, 0.0f, -1.0f, -1.0f}),
+ mTransform(Transform::None),
+ mVisibleRegion(),
+ mZ(0),
+ mReleaseFence(),
+ mHwc1Id(0),
+ mHasUnsupportedPlaneAlpha(false) {}
+
+bool HWC2On1Adapter::SortLayersByZ::operator()(
+ const std::shared_ptr<Layer>& lhs, const std::shared_ptr<Layer>& rhs) {
+ return lhs->getZ() < rhs->getZ();
+}
+
+Error HWC2On1Adapter::Layer::setBuffer(buffer_handle_t buffer,
+ int32_t acquireFence) {
+ ALOGV("Setting acquireFence to %d for layer %" PRIu64, acquireFence, mId);
+ mBuffer.setBuffer(buffer);
+ mBuffer.setFence(acquireFence);
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setCursorPosition(int32_t x, int32_t y) {
+ if (mCompositionType != Composition::Cursor) {
+ return Error::BadLayer;
+ }
+
+ if (mDisplay.hasChanges()) {
+ return Error::NotValidated;
+ }
+
+ auto displayId = mDisplay.getHwc1Id();
+ auto hwc1Device = mDisplay.getDevice().getHwc1Device();
+ hwc1Device->setCursorPositionAsync(hwc1Device, displayId, x, y);
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setSurfaceDamage(hwc_region_t damage) {
+ // HWC1 supports surface damage starting only with version 1.5.
+ if (mDisplay.getDevice().mHwc1MinorVersion < 5) {
+ return Error::None;
+ }
+ mSurfaceDamage.resize(damage.numRects);
+ std::copy_n(damage.rects, damage.numRects, mSurfaceDamage.begin());
+ return Error::None;
+}
+
+// Layer state functions
+
+Error HWC2On1Adapter::Layer::setBlendMode(BlendMode mode) {
+ mBlendMode = mode;
+ mDisplay.markGeometryChanged();
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setColor(hwc_color_t color) {
+ mColor = color;
+ mDisplay.markGeometryChanged();
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setCompositionType(Composition type) {
+ mCompositionType = type;
+ mDisplay.markGeometryChanged();
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setDataspace(android_dataspace_t) {
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setDisplayFrame(hwc_rect_t frame) {
+ mDisplayFrame = frame;
+ mDisplay.markGeometryChanged();
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setPlaneAlpha(float alpha) {
+ mPlaneAlpha = alpha;
+ mDisplay.markGeometryChanged();
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setSidebandStream(const native_handle_t* stream) {
+ mSidebandStream = stream;
+ mDisplay.markGeometryChanged();
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setSourceCrop(hwc_frect_t crop) {
+ mSourceCrop = crop;
+ mDisplay.markGeometryChanged();
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setTransform(Transform transform) {
+ mTransform = transform;
+ mDisplay.markGeometryChanged();
+ return Error::None;
+}
+
+static bool compareRects(const hwc_rect_t& rect1, const hwc_rect_t& rect2) {
+ return rect1.left == rect2.left &&
+ rect1.right == rect2.right &&
+ rect1.top == rect2.top &&
+ rect1.bottom == rect2.bottom;
+}
+
+Error HWC2On1Adapter::Layer::setVisibleRegion(hwc_region_t visible) {
+ if ((getNumVisibleRegions() != visible.numRects) ||
+ !std::equal(mVisibleRegion.begin(), mVisibleRegion.end(), visible.rects,
+ compareRects)) {
+ mVisibleRegion.resize(visible.numRects);
+ std::copy_n(visible.rects, visible.numRects, mVisibleRegion.begin());
+ mDisplay.markGeometryChanged();
+ }
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setZ(uint32_t z) {
+ mZ = z;
+ return Error::None;
+}
+
+void HWC2On1Adapter::Layer::addReleaseFence(int fenceFd) {
+ ALOGV("addReleaseFence %d to layer %" PRIu64, fenceFd, mId);
+ mReleaseFence.add(fenceFd);
+}
+
+const sp<MiniFence>& HWC2On1Adapter::Layer::getReleaseFence() const {
+ return mReleaseFence.get();
+}
+
+void HWC2On1Adapter::Layer::applyState(hwc_layer_1_t& hwc1Layer) {
+ applyCommonState(hwc1Layer);
+ applyCompositionType(hwc1Layer);
+ switch (mCompositionType) {
+ case Composition::SolidColor : applySolidColorState(hwc1Layer); break;
+ case Composition::Sideband : applySidebandState(hwc1Layer); break;
+ default: applyBufferState(hwc1Layer); break;
+ }
+}
+
+static std::string regionStrings(const std::vector<hwc_rect_t>& visibleRegion,
+ const std::vector<hwc_rect_t>& surfaceDamage) {
+ std::string regions;
+ regions += " Visible Region";
+ regions.resize(40, ' ');
+ regions += "Surface Damage\n";
+
+ size_t numPrinted = 0;
+ size_t maxSize = std::max(visibleRegion.size(), surfaceDamage.size());
+ while (numPrinted < maxSize) {
+ std::string line(" ");
+ if (visibleRegion.empty() && numPrinted == 0) {
+ line += "None";
+ } else if (numPrinted < visibleRegion.size()) {
+ line += rectString(visibleRegion[numPrinted]);
+ }
+ line.resize(40, ' ');
+ if (surfaceDamage.empty() && numPrinted == 0) {
+ line += "None";
+ } else if (numPrinted < surfaceDamage.size()) {
+ line += rectString(surfaceDamage[numPrinted]);
+ }
+ line += '\n';
+ regions += line;
+ ++numPrinted;
+ }
+ return regions;
+}
+
+std::string HWC2On1Adapter::Layer::dump() const {
+ std::stringstream output;
+ const char* fill = " ";
+
+ output << fill << to_string(mCompositionType);
+ output << " Layer HWC2/1: " << mId << "/" << mHwc1Id << " ";
+ output << "Z: " << mZ;
+ if (mCompositionType == HWC2::Composition::SolidColor) {
+ output << " " << colorString(mColor);
+ } else if (mCompositionType == HWC2::Composition::Sideband) {
+ output << " Handle: " << mSidebandStream << '\n';
+ } else {
+ output << " Buffer: " << mBuffer.getBuffer() << "/" <<
+ mBuffer.getFence() << '\n';
+ output << fill << " Display frame [LTRB]: " <<
+ rectString(mDisplayFrame) << '\n';
+ output << fill << " Source crop: " <<
+ frectString(mSourceCrop) << '\n';
+ output << fill << " Transform: " << to_string(mTransform);
+ output << " Blend mode: " << to_string(mBlendMode);
+ if (mPlaneAlpha != 1.0f) {
+ output << " Alpha: " <<
+ alphaString(mPlaneAlpha) << '\n';
+ } else {
+ output << '\n';
+ }
+ output << regionStrings(mVisibleRegion, mSurfaceDamage);
+ }
+ return output.str();
+}
+
+static int getHwc1Blending(HWC2::BlendMode blendMode) {
+ switch (blendMode) {
+ case BlendMode::Coverage: return HWC_BLENDING_COVERAGE;
+ case BlendMode::Premultiplied: return HWC_BLENDING_PREMULT;
+ default: return HWC_BLENDING_NONE;
+ }
+}
+
+void HWC2On1Adapter::Layer::applyCommonState(hwc_layer_1_t& hwc1Layer) {
+ auto minorVersion = mDisplay.getDevice().getHwc1MinorVersion();
+ hwc1Layer.blending = getHwc1Blending(mBlendMode);
+ hwc1Layer.displayFrame = mDisplayFrame;
+
+ auto pendingAlpha = mPlaneAlpha;
+ if (minorVersion < 2) {
+ mHasUnsupportedPlaneAlpha = pendingAlpha < 1.0f;
+ } else {
+ hwc1Layer.planeAlpha =
+ static_cast<uint8_t>(255.0f * pendingAlpha + 0.5f);
+ }
+
+ if (minorVersion < 3) {
+ auto pending = mSourceCrop;
+ hwc1Layer.sourceCropi.left =
+ static_cast<int32_t>(std::ceil(pending.left));
+ hwc1Layer.sourceCropi.top =
+ static_cast<int32_t>(std::ceil(pending.top));
+ hwc1Layer.sourceCropi.right =
+ static_cast<int32_t>(std::floor(pending.right));
+ hwc1Layer.sourceCropi.bottom =
+ static_cast<int32_t>(std::floor(pending.bottom));
+ } else {
+ hwc1Layer.sourceCropf = mSourceCrop;
+ }
+
+ hwc1Layer.transform = static_cast<uint32_t>(mTransform);
+
+ auto& hwc1VisibleRegion = hwc1Layer.visibleRegionScreen;
+ hwc1VisibleRegion.numRects = mVisibleRegion.size();
+ hwc_rect_t* rects = mDisplay.GetRects(hwc1VisibleRegion.numRects);
+ hwc1VisibleRegion.rects = rects;
+ for (size_t i = 0; i < mVisibleRegion.size(); i++) {
+ rects[i] = mVisibleRegion[i];
+ }
+}
+
+void HWC2On1Adapter::Layer::applySolidColorState(hwc_layer_1_t& hwc1Layer) {
+ // If the device does not support background color it is likely to make
+ // assumption regarding backgroundColor and handle (both fields occupy
+ // the same location in hwc_layer_1_t union).
+ // To not confuse these devices we don't set background color and we
+ // make sure handle is a null pointer.
+ if (hasUnsupportedBackgroundColor()) {
+ hwc1Layer.handle = nullptr;
+ } else {
+ hwc1Layer.backgroundColor = mColor;
+ }
+}
+
+void HWC2On1Adapter::Layer::applySidebandState(hwc_layer_1_t& hwc1Layer) {
+ hwc1Layer.sidebandStream = mSidebandStream;
+}
+
+void HWC2On1Adapter::Layer::applyBufferState(hwc_layer_1_t& hwc1Layer) {
+ hwc1Layer.handle = mBuffer.getBuffer();
+ hwc1Layer.acquireFenceFd = mBuffer.getFence();
+}
+
+void HWC2On1Adapter::Layer::applyCompositionType(hwc_layer_1_t& hwc1Layer) {
+ // HWC1 never supports color transforms or dataspaces and only sometimes
+ // supports plane alpha (depending on the version). These require us to drop
+ // some or all layers to client composition.
+ if (mHasUnsupportedPlaneAlpha || mDisplay.hasColorTransform() ||
+ hasUnsupportedBackgroundColor()) {
+ hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+ hwc1Layer.flags = HWC_SKIP_LAYER;
+ return;
+ }
+
+ hwc1Layer.flags = 0;
+ switch (mCompositionType) {
+ case Composition::Client:
+ hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+ hwc1Layer.flags |= HWC_SKIP_LAYER;
+ break;
+ case Composition::Device:
+ hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+ break;
+ case Composition::SolidColor:
+ // In theory the following line should work, but since the HWC1
+ // version of SurfaceFlinger never used HWC_BACKGROUND, HWC1
+ // devices may not work correctly. To be on the safe side, we
+ // fall back to client composition.
+ //
+ // hwc1Layer.compositionType = HWC_BACKGROUND;
+ hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+ hwc1Layer.flags |= HWC_SKIP_LAYER;
+ break;
+ case Composition::Cursor:
+ hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+ if (mDisplay.getDevice().getHwc1MinorVersion() >= 4) {
+ hwc1Layer.hints |= HWC_IS_CURSOR_LAYER;
+ }
+ break;
+ case Composition::Sideband:
+ if (mDisplay.getDevice().getHwc1MinorVersion() < 4) {
+ hwc1Layer.compositionType = HWC_SIDEBAND;
+ } else {
+ hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+ hwc1Layer.flags |= HWC_SKIP_LAYER;
+ }
+ break;
+ default:
+ hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+ hwc1Layer.flags |= HWC_SKIP_LAYER;
+ break;
+ }
+ ALOGV("Layer %" PRIu64 " %s set to %d", mId,
+ to_string(mCompositionType).c_str(),
+ hwc1Layer.compositionType);
+ ALOGV_IF(hwc1Layer.flags & HWC_SKIP_LAYER, " and skipping");
+}
+
+// Adapter helpers
+
+void HWC2On1Adapter::populateCapabilities() {
+ if (mHwc1MinorVersion >= 3U) {
+ int supportedTypes = 0;
+ auto result = mHwc1Device->query(mHwc1Device,
+ HWC_DISPLAY_TYPES_SUPPORTED, &supportedTypes);
+ if ((result == 0) && ((supportedTypes & HWC_DISPLAY_VIRTUAL_BIT) != 0)) {
+ ALOGI("Found support for HWC virtual displays");
+ mHwc1SupportsVirtualDisplays = true;
+ }
+ }
+ if (mHwc1MinorVersion >= 4U) {
+ mCapabilities.insert(Capability::SidebandStream);
+ }
+
+ // Check for HWC background color layer support.
+ if (mHwc1MinorVersion >= 1U) {
+ int backgroundColorSupported = 0;
+ auto result = mHwc1Device->query(mHwc1Device,
+ HWC_BACKGROUND_LAYER_SUPPORTED,
+ &backgroundColorSupported);
+ if ((result == 0) && (backgroundColorSupported == 1)) {
+ ALOGV("Found support for HWC background color");
+ mHwc1SupportsBackgroundColor = true;
+ }
+ }
+
+ // Some devices might have HWC1 retire fences that accurately emulate
+ // HWC2 present fences when they are deferred, but it's not very reliable.
+ // To be safe, we indicate PresentFenceIsNotReliable for all HWC1 devices.
+ mCapabilities.insert(Capability::PresentFenceIsNotReliable);
+}
+
+HWC2On1Adapter::Display* HWC2On1Adapter::getDisplay(hwc2_display_t id) {
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+ auto display = mDisplays.find(id);
+ if (display == mDisplays.end()) {
+ return nullptr;
+ }
+
+ return display->second.get();
+}
+
+std::tuple<HWC2On1Adapter::Layer*, Error> HWC2On1Adapter::getLayer(
+ hwc2_display_t displayId, hwc2_layer_t layerId) {
+ auto display = getDisplay(displayId);
+ if (!display) {
+ return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadDisplay);
+ }
+
+ auto layerEntry = mLayers.find(layerId);
+ if (layerEntry == mLayers.end()) {
+ return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadLayer);
+ }
+
+ auto layer = layerEntry->second;
+ if (layer->getDisplay().getId() != displayId) {
+ return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadLayer);
+ }
+ return std::make_tuple(layer.get(), Error::None);
+}
+
+void HWC2On1Adapter::populatePrimary() {
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+ auto display = std::make_shared<Display>(*this, HWC2::DisplayType::Physical);
+ mHwc1DisplayMap[HWC_DISPLAY_PRIMARY] = display->getId();
+ display->setHwc1Id(HWC_DISPLAY_PRIMARY);
+ display->populateConfigs();
+ mDisplays.emplace(display->getId(), std::move(display));
+}
+
+bool HWC2On1Adapter::prepareAllDisplays() {
+ ATRACE_CALL();
+
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+ for (const auto& displayPair : mDisplays) {
+ auto& display = displayPair.second;
+ if (!display->prepare()) {
+ return false;
+ }
+ }
+
+ if (mHwc1DisplayMap.count(HWC_DISPLAY_PRIMARY) == 0) {
+ ALOGE("prepareAllDisplays: Unable to find primary HWC1 display");
+ return false;
+ }
+
+ // Build an array of hwc_display_contents_1 to call prepare() on HWC1.
+ mHwc1Contents.clear();
+
+ // Always push the primary display
+ auto primaryDisplayId = mHwc1DisplayMap[HWC_DISPLAY_PRIMARY];
+ auto& primaryDisplay = mDisplays[primaryDisplayId];
+ mHwc1Contents.push_back(primaryDisplay->getDisplayContents());
+
+ // Push the external display, if present
+ if (mHwc1DisplayMap.count(HWC_DISPLAY_EXTERNAL) != 0) {
+ auto externalDisplayId = mHwc1DisplayMap[HWC_DISPLAY_EXTERNAL];
+ auto& externalDisplay = mDisplays[externalDisplayId];
+ mHwc1Contents.push_back(externalDisplay->getDisplayContents());
+ } else {
+ // Even if an external display isn't present, we still need to send
+ // at least two displays down to HWC1
+ mHwc1Contents.push_back(nullptr);
+ }
+
+ // Push the hardware virtual display, if supported and present
+ if (mHwc1MinorVersion >= 3) {
+ if (mHwc1DisplayMap.count(HWC_DISPLAY_VIRTUAL) != 0) {
+ auto virtualDisplayId = mHwc1DisplayMap[HWC_DISPLAY_VIRTUAL];
+ auto& virtualDisplay = mDisplays[virtualDisplayId];
+ mHwc1Contents.push_back(virtualDisplay->getDisplayContents());
+ } else {
+ mHwc1Contents.push_back(nullptr);
+ }
+ }
+
+ for (auto& displayContents : mHwc1Contents) {
+ if (!displayContents) {
+ continue;
+ }
+
+ ALOGV("Display %zd layers:", mHwc1Contents.size() - 1);
+ for (size_t l = 0; l < displayContents->numHwLayers; ++l) {
+ auto& layer = displayContents->hwLayers[l];
+ ALOGV(" %zd: %d", l, layer.compositionType);
+ }
+ }
+
+ ALOGV("Calling HWC1 prepare");
+ {
+ ATRACE_NAME("HWC1 prepare");
+ mHwc1Device->prepare(mHwc1Device, mHwc1Contents.size(),
+ mHwc1Contents.data());
+ }
+
+ for (size_t c = 0; c < mHwc1Contents.size(); ++c) {
+ auto& contents = mHwc1Contents[c];
+ if (!contents) {
+ continue;
+ }
+ ALOGV("Display %zd layers:", c);
+ for (size_t l = 0; l < contents->numHwLayers; ++l) {
+ ALOGV(" %zd: %d", l, contents->hwLayers[l].compositionType);
+ }
+ }
+
+ // Return the received contents to their respective displays
+ for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) {
+ if (mHwc1Contents[hwc1Id] == nullptr) {
+ continue;
+ }
+
+ auto displayId = mHwc1DisplayMap[hwc1Id];
+ auto& display = mDisplays[displayId];
+ display->generateChanges();
+ }
+
+ return true;
+}
+
+void dumpHWC1Message(hwc_composer_device_1* device, size_t numDisplays,
+ hwc_display_contents_1_t** displays) {
+ ALOGV("*****************************");
+ size_t displayId = 0;
+ while (displayId < numDisplays) {
+ hwc_display_contents_1_t* display = displays[displayId];
+
+ ALOGV("hwc_display_contents_1_t[%zu] @0x%p", displayId, display);
+ if (display == nullptr) {
+ displayId++;
+ continue;
+ }
+ ALOGV(" retirefd:0x%08x", display->retireFenceFd);
+ ALOGV(" outbuf :0x%p", display->outbuf);
+ ALOGV(" outbuffd:0x%08x", display->outbufAcquireFenceFd);
+ ALOGV(" flags :0x%08x", display->flags);
+ for(size_t layerId=0 ; layerId < display->numHwLayers ; layerId++) {
+ hwc_layer_1_t& layer = display->hwLayers[layerId];
+ ALOGV(" Layer[%zu]:", layerId);
+ ALOGV(" composition : 0x%08x", layer.compositionType);
+ ALOGV(" hints : 0x%08x", layer.hints);
+ ALOGV(" flags : 0x%08x", layer.flags);
+ ALOGV(" handle : 0x%p", layer.handle);
+ ALOGV(" transform : 0x%08x", layer.transform);
+ ALOGV(" blending : 0x%08x", layer.blending);
+ ALOGV(" sourceCropf : %f, %f, %f, %f",
+ layer.sourceCropf.left,
+ layer.sourceCropf.top,
+ layer.sourceCropf.right,
+ layer.sourceCropf.bottom);
+ ALOGV(" displayFrame : %d, %d, %d, %d",
+ layer.displayFrame.left,
+ layer.displayFrame.left,
+ layer.displayFrame.left,
+ layer.displayFrame.left);
+ hwc_region_t& visReg = layer.visibleRegionScreen;
+ ALOGV(" visibleRegionScreen: #0x%08zx[@0x%p]",
+ visReg.numRects,
+ visReg.rects);
+ for (size_t visRegId=0; visRegId < visReg.numRects ; visRegId++) {
+ if (layer.visibleRegionScreen.rects == nullptr) {
+ ALOGV(" null");
+ } else {
+ ALOGV(" visibleRegionScreen[%zu] %d, %d, %d, %d",
+ visRegId,
+ visReg.rects[visRegId].left,
+ visReg.rects[visRegId].top,
+ visReg.rects[visRegId].right,
+ visReg.rects[visRegId].bottom);
+ }
+ }
+ ALOGV(" acquireFenceFd : 0x%08x", layer.acquireFenceFd);
+ ALOGV(" releaseFenceFd : 0x%08x", layer.releaseFenceFd);
+ ALOGV(" planeAlpha : 0x%08x", layer.planeAlpha);
+ if (getMinorVersion(device) < 5)
+ continue;
+ ALOGV(" surfaceDamage : #0x%08zx[@0x%p]",
+ layer.surfaceDamage.numRects,
+ layer.surfaceDamage.rects);
+ for (size_t sdId=0; sdId < layer.surfaceDamage.numRects ; sdId++) {
+ if (layer.surfaceDamage.rects == nullptr) {
+ ALOGV(" null");
+ } else {
+ ALOGV(" surfaceDamage[%zu] %d, %d, %d, %d",
+ sdId,
+ layer.surfaceDamage.rects[sdId].left,
+ layer.surfaceDamage.rects[sdId].top,
+ layer.surfaceDamage.rects[sdId].right,
+ layer.surfaceDamage.rects[sdId].bottom);
+ }
+ }
+ }
+ displayId++;
+ }
+ ALOGV("-----------------------------");
+}
+
+Error HWC2On1Adapter::setAllDisplays() {
+ ATRACE_CALL();
+
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+ // Make sure we're ready to validate
+ for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) {
+ if (mHwc1Contents[hwc1Id] == nullptr) {
+ continue;
+ }
+
+ auto displayId = mHwc1DisplayMap[hwc1Id];
+ auto& display = mDisplays[displayId];
+ Error error = display->set(*mHwc1Contents[hwc1Id]);
+ if (error != Error::None) {
+ ALOGE("setAllDisplays: Failed to set display %zd: %s", hwc1Id,
+ to_string(error).c_str());
+ return error;
+ }
+ }
+
+ ALOGV("Calling HWC1 set");
+ {
+ ATRACE_NAME("HWC1 set");
+ //dumpHWC1Message(mHwc1Device, mHwc1Contents.size(), mHwc1Contents.data());
+ mHwc1Device->set(mHwc1Device, mHwc1Contents.size(),
+ mHwc1Contents.data());
+ }
+
+ // Add retire and release fences
+ for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) {
+ if (mHwc1Contents[hwc1Id] == nullptr) {
+ continue;
+ }
+
+ auto displayId = mHwc1DisplayMap[hwc1Id];
+ auto& display = mDisplays[displayId];
+ auto retireFenceFd = mHwc1Contents[hwc1Id]->retireFenceFd;
+ ALOGV("setAllDisplays: Adding retire fence %d to display %zd",
+ retireFenceFd, hwc1Id);
+ display->addRetireFence(mHwc1Contents[hwc1Id]->retireFenceFd);
+ display->addReleaseFences(*mHwc1Contents[hwc1Id]);
+ }
+
+ return Error::None;
+}
+
+void HWC2On1Adapter::hwc1Invalidate() {
+ ALOGV("Received hwc1Invalidate");
+
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+ // If the HWC2-side callback hasn't been registered yet, buffer this until
+ // it is registered.
+ if (mCallbacks.count(Callback::Refresh) == 0) {
+ mHasPendingInvalidate = true;
+ return;
+ }
+
+ const auto& callbackInfo = mCallbacks[Callback::Refresh];
+ std::vector<hwc2_display_t> displays;
+ for (const auto& displayPair : mDisplays) {
+ displays.emplace_back(displayPair.first);
+ }
+
+ // Call back without the state lock held.
+ lock.unlock();
+
+ auto refresh = reinterpret_cast<HWC2_PFN_REFRESH>(callbackInfo.pointer);
+ for (auto display : displays) {
+ refresh(callbackInfo.data, display);
+ }
+}
+
+void HWC2On1Adapter::hwc1Vsync(int hwc1DisplayId, int64_t timestamp) {
+ ALOGV("Received hwc1Vsync(%d, %" PRId64 ")", hwc1DisplayId, timestamp);
+
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+ // If the HWC2-side callback hasn't been registered yet, buffer this until
+ // it is registered.
+ if (mCallbacks.count(Callback::Vsync) == 0) {
+ mPendingVsyncs.emplace_back(hwc1DisplayId, timestamp);
+ return;
+ }
+
+ if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
+ ALOGE("hwc1Vsync: Couldn't find display for HWC1 id %d", hwc1DisplayId);
+ return;
+ }
+
+ const auto& callbackInfo = mCallbacks[Callback::Vsync];
+ auto displayId = mHwc1DisplayMap[hwc1DisplayId];
+
+ // Call back without the state lock held.
+ lock.unlock();
+
+ auto vsync = reinterpret_cast<HWC2_PFN_VSYNC>(callbackInfo.pointer);
+ vsync(callbackInfo.data, displayId, timestamp);
+}
+
+void HWC2On1Adapter::hwc1Hotplug(int hwc1DisplayId, int connected) {
+ ALOGV("Received hwc1Hotplug(%d, %d)", hwc1DisplayId, connected);
+
+ if (hwc1DisplayId != HWC_DISPLAY_EXTERNAL) {
+ ALOGE("hwc1Hotplug: Received hotplug for non-external display");
+ return;
+ }
+
+ std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+ // If the HWC2-side callback hasn't been registered yet, buffer this until
+ // it is registered
+ if (mCallbacks.count(Callback::Hotplug) == 0) {
+ mPendingHotplugs.emplace_back(hwc1DisplayId, connected);
+ return;
+ }
+
+ hwc2_display_t displayId = UINT64_MAX;
+ if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
+ if (connected == 0) {
+ ALOGW("hwc1Hotplug: Received disconnect for unconnected display");
+ return;
+ }
+
+ // Create a new display on connect
+ auto display = std::make_shared<HWC2On1Adapter::Display>(*this,
+ HWC2::DisplayType::Physical);
+ display->setHwc1Id(HWC_DISPLAY_EXTERNAL);
+ display->populateConfigs();
+ displayId = display->getId();
+ mHwc1DisplayMap[HWC_DISPLAY_EXTERNAL] = displayId;
+ mDisplays.emplace(displayId, std::move(display));
+ } else {
+ if (connected != 0) {
+ ALOGW("hwc1Hotplug: Received connect for previously connected "
+ "display");
+ return;
+ }
+
+ // Disconnect an existing display
+ displayId = mHwc1DisplayMap[hwc1DisplayId];
+ mHwc1DisplayMap.erase(HWC_DISPLAY_EXTERNAL);
+ mDisplays.erase(displayId);
+ }
+
+ const auto& callbackInfo = mCallbacks[Callback::Hotplug];
+
+ // Call back without the state lock held
+ lock.unlock();
+
+ auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(callbackInfo.pointer);
+ auto hwc2Connected = (connected == 0) ?
+ HWC2::Connection::Disconnected : HWC2::Connection::Connected;
+ hotplug(callbackInfo.data, displayId, static_cast<int32_t>(hwc2Connected));
+}
+} // namespace android
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/MiniFence.cpp b/graphics/composer/2.1/utils/hwc2on1adapter/MiniFence.cpp
new file mode 100644
index 0000000..dfbe4d6
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/MiniFence.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2017 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 "hwc2on1adapter/MiniFence.h"
+
+#include <unistd.h>
+
+namespace android {
+
+const sp<MiniFence> MiniFence::NO_FENCE = sp<MiniFence>(new MiniFence);
+
+MiniFence::MiniFence() :
+ mFenceFd(-1) {
+}
+
+MiniFence::MiniFence(int fenceFd) :
+ mFenceFd(fenceFd) {
+}
+
+MiniFence::~MiniFence() {
+ if (mFenceFd != -1) {
+ close(mFenceFd);
+ }
+}
+
+int MiniFence::dup() const {
+ return ::dup(mFenceFd);
+}
+}
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h b/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h
new file mode 100644
index 0000000..3badfce
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h
@@ -0,0 +1,738 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SF_HWC2_ON_1_ADAPTER_H
+#define ANDROID_SF_HWC2_ON_1_ADAPTER_H
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include "MiniFence.h"
+
+#include <atomic>
+#include <map>
+#include <mutex>
+#include <queue>
+#include <set>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+struct hwc_composer_device_1;
+struct hwc_display_contents_1;
+struct hwc_layer_1;
+
+namespace android {
+
+// For devices unable to provide an implementation of HWC2 (see hwcomposer2.h),
+// we provide an adapter able to talk to HWC1 (see hwcomposer.h). It translates
+// streamed function calls ala HWC2 model to batched array of structs calls ala
+// HWC1 model.
+class HWC2On1Adapter : public hwc2_device_t
+{
+public:
+ explicit HWC2On1Adapter(struct hwc_composer_device_1* hwc1Device);
+ ~HWC2On1Adapter();
+
+ struct hwc_composer_device_1* getHwc1Device() const { return mHwc1Device; }
+ uint8_t getHwc1MinorVersion() const { return mHwc1MinorVersion; }
+
+private:
+ static inline HWC2On1Adapter* getAdapter(hwc2_device_t* device) {
+ return static_cast<HWC2On1Adapter*>(device);
+ }
+
+ // getCapabilities
+
+ void doGetCapabilities(uint32_t* outCount,
+ int32_t* /*hwc2_capability_t*/ outCapabilities);
+ static void getCapabilitiesHook(hwc2_device_t* device, uint32_t* outCount,
+ int32_t* /*hwc2_capability_t*/ outCapabilities) {
+ getAdapter(device)->doGetCapabilities(outCount, outCapabilities);
+ }
+
+ bool supportsBackgroundColor() {
+ return mHwc1SupportsBackgroundColor;
+ }
+
+ // getFunction
+
+ hwc2_function_pointer_t doGetFunction(HWC2::FunctionDescriptor descriptor);
+ static hwc2_function_pointer_t getFunctionHook(hwc2_device_t* device,
+ int32_t intDesc) {
+ auto descriptor = static_cast<HWC2::FunctionDescriptor>(intDesc);
+ return getAdapter(device)->doGetFunction(descriptor);
+ }
+
+ // Device functions
+
+ HWC2::Error createVirtualDisplay(uint32_t width, uint32_t height,
+ hwc2_display_t* outDisplay);
+ static int32_t createVirtualDisplayHook(hwc2_device_t* device,
+ uint32_t width, uint32_t height, int32_t* /*format*/,
+ hwc2_display_t* outDisplay) {
+ // HWC1 implementations cannot override the buffer format requested by
+ // the consumer
+ auto error = getAdapter(device)->createVirtualDisplay(width, height,
+ outDisplay);
+ return static_cast<int32_t>(error);
+ }
+
+ HWC2::Error destroyVirtualDisplay(hwc2_display_t display);
+ static int32_t destroyVirtualDisplayHook(hwc2_device_t* device,
+ hwc2_display_t display) {
+ auto error = getAdapter(device)->destroyVirtualDisplay(display);
+ return static_cast<int32_t>(error);
+ }
+
+ std::string mDumpString;
+ void dump(uint32_t* outSize, char* outBuffer);
+ static void dumpHook(hwc2_device_t* device, uint32_t* outSize,
+ char* outBuffer) {
+ getAdapter(device)->dump(outSize, outBuffer);
+ }
+
+ uint32_t getMaxVirtualDisplayCount();
+ static uint32_t getMaxVirtualDisplayCountHook(hwc2_device_t* device) {
+ return getAdapter(device)->getMaxVirtualDisplayCount();
+ }
+
+ HWC2::Error registerCallback(HWC2::Callback descriptor,
+ hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer);
+ static int32_t registerCallbackHook(hwc2_device_t* device,
+ int32_t intDesc, hwc2_callback_data_t callbackData,
+ hwc2_function_pointer_t pointer) {
+ auto descriptor = static_cast<HWC2::Callback>(intDesc);
+ auto error = getAdapter(device)->registerCallback(descriptor,
+ callbackData, pointer);
+ return static_cast<int32_t>(error);
+ }
+
+ // Display functions
+
+ class Layer;
+
+ class SortLayersByZ {
+ public:
+ bool operator()(const std::shared_ptr<Layer>& lhs,
+ const std::shared_ptr<Layer>& rhs);
+ };
+
+ // The semantics of the fences returned by the device differ between
+ // hwc1.set() and hwc2.present(). Read hwcomposer.h and hwcomposer2.h
+ // for more information.
+ //
+ // Release fences in hwc1 are obtained on set() for a frame n and signaled
+ // when the layer buffer is not needed for read operations anymore
+ // (typically on frame n+1). In HWC2, release fences are obtained with a
+ // special call after present() for frame n. These fences signal
+ // on frame n: More specifically, the fence for a given buffer provided in
+ // frame n will signal when the prior buffer is no longer required.
+ //
+ // A retire fence (HWC1) is signaled when a composition is replaced
+ // on the panel whereas a present fence (HWC2) is signaled when a
+ // composition starts to be displayed on a panel.
+ //
+ // The HWC2to1Adapter emulates the new fence semantics for a frame
+ // n by returning the fence from frame n-1. For frame 0, the adapter
+ // returns NO_FENCE.
+ class DeferredFence {
+ public:
+ DeferredFence()
+ : mFences({MiniFence::NO_FENCE, MiniFence::NO_FENCE}) {}
+
+ void add(int32_t fenceFd) {
+ mFences.emplace(new MiniFence(fenceFd));
+ mFences.pop();
+ }
+
+ const sp<MiniFence>& get() const {
+ return mFences.front();
+ }
+
+ private:
+ // There are always two fences in this queue.
+ std::queue<sp<MiniFence>> mFences;
+ };
+
+ class FencedBuffer {
+ public:
+ FencedBuffer() : mBuffer(nullptr), mFence(MiniFence::NO_FENCE) {}
+
+ void setBuffer(buffer_handle_t buffer) { mBuffer = buffer; }
+ void setFence(int fenceFd) { mFence = new MiniFence(fenceFd); }
+
+ buffer_handle_t getBuffer() const { return mBuffer; }
+ int getFence() const { return mFence->dup(); }
+
+ private:
+ buffer_handle_t mBuffer;
+ sp<MiniFence> mFence;
+ };
+
+ class Display {
+ public:
+ Display(HWC2On1Adapter& device, HWC2::DisplayType type);
+
+ hwc2_display_t getId() const { return mId; }
+ HWC2On1Adapter& getDevice() const { return mDevice; }
+
+ // Does not require locking because it is set before adding the
+ // Displays to the Adapter's list of displays
+ void setHwc1Id(int32_t id) { mHwc1Id = id; }
+ int32_t getHwc1Id() const { return mHwc1Id; }
+
+ // HWC2 Display functions
+ HWC2::Error acceptChanges();
+ HWC2::Error createLayer(hwc2_layer_t* outLayerId);
+ HWC2::Error destroyLayer(hwc2_layer_t layerId);
+ HWC2::Error getActiveConfig(hwc2_config_t* outConfigId);
+ HWC2::Error getAttribute(hwc2_config_t configId,
+ HWC2::Attribute attribute, int32_t* outValue);
+ HWC2::Error getChangedCompositionTypes(uint32_t* outNumElements,
+ hwc2_layer_t* outLayers, int32_t* outTypes);
+ HWC2::Error getColorModes(uint32_t* outNumModes, int32_t* outModes);
+ HWC2::Error getConfigs(uint32_t* outNumConfigs,
+ hwc2_config_t* outConfigIds);
+ HWC2::Error getDozeSupport(int32_t* outSupport);
+ HWC2::Error getHdrCapabilities(uint32_t* outNumTypes,
+ int32_t* outTypes, float* outMaxLuminance,
+ float* outMaxAverageLuminance, float* outMinLuminance);
+ HWC2::Error getName(uint32_t* outSize, char* outName);
+ HWC2::Error getReleaseFences(uint32_t* outNumElements,
+ hwc2_layer_t* outLayers, int32_t* outFences);
+ HWC2::Error getRequests(int32_t* outDisplayRequests,
+ uint32_t* outNumElements, hwc2_layer_t* outLayers,
+ int32_t* outLayerRequests);
+ HWC2::Error getType(int32_t* outType);
+
+ // Since HWC1 "presents" (called "set" in HWC1) all Displays
+ // at once, the first call to any Display::present will trigger
+ // present() on all Displays in the Device. Subsequent calls without
+ // first calling validate() are noop (except for duping/returning
+ // the retire fence).
+ HWC2::Error present(int32_t* outRetireFence);
+
+ HWC2::Error setActiveConfig(hwc2_config_t configId);
+ HWC2::Error setClientTarget(buffer_handle_t target,
+ int32_t acquireFence, int32_t dataspace,
+ hwc_region_t damage);
+ HWC2::Error setColorMode(android_color_mode_t mode);
+ HWC2::Error setColorTransform(android_color_transform_t hint);
+ HWC2::Error setOutputBuffer(buffer_handle_t buffer,
+ int32_t releaseFence);
+ HWC2::Error setPowerMode(HWC2::PowerMode mode);
+ HWC2::Error setVsyncEnabled(HWC2::Vsync enabled);
+
+ // Since HWC1 "validates" (called "prepare" in HWC1) all Displays
+ // at once, the first call to any Display::validate() will trigger
+ // validate() on all other Displays in the Device.
+ HWC2::Error validate(uint32_t* outNumTypes,
+ uint32_t* outNumRequests);
+
+ HWC2::Error updateLayerZ(hwc2_layer_t layerId, uint32_t z);
+
+ HWC2::Error getClientTargetSupport(uint32_t width, uint32_t height,
+ int32_t format, int32_t dataspace);
+
+ // Read configs from HWC1 device
+ void populateConfigs();
+
+ // Set configs for a virtual display
+ void populateConfigs(uint32_t width, uint32_t height);
+
+ bool prepare();
+
+ // Called after hwc.prepare() with responses from the device.
+ void generateChanges();
+
+ bool hasChanges() const;
+ HWC2::Error set(hwc_display_contents_1& hwcContents);
+ void addRetireFence(int fenceFd);
+ void addReleaseFences(const hwc_display_contents_1& hwcContents);
+
+ bool hasColorTransform() const;
+
+ std::string dump() const;
+
+ // Return a rect from the pool allocated during validate()
+ hwc_rect_t* GetRects(size_t numRects);
+
+ hwc_display_contents_1* getDisplayContents();
+
+ void markGeometryChanged() { mGeometryChanged = true; }
+ void resetGeometryMarker() { mGeometryChanged = false;}
+ private:
+ class Config {
+ public:
+ Config(Display& display)
+ : mDisplay(display),
+ mId(0),
+ mAttributes() {}
+
+ bool isOnDisplay(const Display& display) const {
+ return display.getId() == mDisplay.getId();
+ }
+
+ void setAttribute(HWC2::Attribute attribute, int32_t value);
+ int32_t getAttribute(HWC2::Attribute attribute) const;
+
+ void setHwc1Id(uint32_t id);
+ bool hasHwc1Id(uint32_t id) const;
+ HWC2::Error getColorModeForHwc1Id(uint32_t id,
+ android_color_mode_t *outMode) const;
+ HWC2::Error getHwc1IdForColorMode(android_color_mode_t mode,
+ uint32_t* outId) const;
+
+ void setId(hwc2_config_t id) { mId = id; }
+ hwc2_config_t getId() const { return mId; }
+
+ // Attempts to merge two configs that differ only in color
+ // mode. Returns whether the merge was successful
+ bool merge(const Config& other);
+
+ std::set<android_color_mode_t> getColorModes() const;
+
+ // splitLine divides the output into two lines suitable for
+ // dumpsys SurfaceFlinger
+ std::string toString(bool splitLine = false) const;
+
+ private:
+ Display& mDisplay;
+ hwc2_config_t mId;
+ std::unordered_map<HWC2::Attribute, int32_t> mAttributes;
+
+ // Maps from color transform to HWC1 config ID
+ std::unordered_map<android_color_mode_t, uint32_t> mHwc1Ids;
+ };
+
+ // Stores changes requested from the device upon calling prepare().
+ // Handles change request to:
+ // - Layer composition type.
+ // - Layer hints.
+ class Changes {
+ public:
+ uint32_t getNumTypes() const {
+ return static_cast<uint32_t>(mTypeChanges.size());
+ }
+
+ uint32_t getNumLayerRequests() const {
+ return static_cast<uint32_t>(mLayerRequests.size());
+ }
+
+ const std::unordered_map<hwc2_layer_t, HWC2::Composition>&
+ getTypeChanges() const {
+ return mTypeChanges;
+ }
+
+ const std::unordered_map<hwc2_layer_t, HWC2::LayerRequest>&
+ getLayerRequests() const {
+ return mLayerRequests;
+ }
+
+ void addTypeChange(hwc2_layer_t layerId,
+ HWC2::Composition type) {
+ mTypeChanges.insert({layerId, type});
+ }
+
+ void clearTypeChanges() { mTypeChanges.clear(); }
+
+ void addLayerRequest(hwc2_layer_t layerId,
+ HWC2::LayerRequest request) {
+ mLayerRequests.insert({layerId, request});
+ }
+
+ private:
+ std::unordered_map<hwc2_layer_t, HWC2::Composition>
+ mTypeChanges;
+ std::unordered_map<hwc2_layer_t, HWC2::LayerRequest>
+ mLayerRequests;
+ };
+
+ std::shared_ptr<const Config>
+ getConfig(hwc2_config_t configId) const;
+
+ void populateColorModes();
+ void initializeActiveConfig();
+
+ // Creates a bi-directional mapping between index in HWC1
+ // prepare/set array and Layer object. Stores mapping in
+ // mHwc1LayerMap and also updates Layer's attribute mHwc1Id.
+ void assignHwc1LayerIds();
+
+ // Called after a response to prepare() has been received:
+ // Ingest composition type changes requested by the device.
+ void updateTypeChanges(const struct hwc_layer_1& hwc1Layer,
+ const Layer& layer);
+
+ // Called after a response to prepare() has been received:
+ // Ingest layer hint changes requested by the device.
+ void updateLayerRequests(const struct hwc_layer_1& hwc1Layer,
+ const Layer& layer);
+
+ // Set all fields in HWC1 comm array for layer containing the
+ // HWC_FRAMEBUFFER_TARGET (always the last layer).
+ void prepareFramebufferTarget();
+
+ // Display ID generator.
+ static std::atomic<hwc2_display_t> sNextId;
+ const hwc2_display_t mId;
+
+
+ HWC2On1Adapter& mDevice;
+
+ // The state of this display should only be modified from
+ // SurfaceFlinger's main loop, with the exception of when dump is
+ // called. To prevent a bad state from crashing us during a dump
+ // call, all public calls into Display must acquire this mutex.
+ //
+ // It is recursive because we don't want to deadlock in validate
+ // (or present) when we call HWC2On1Adapter::prepareAllDisplays
+ // (or setAllDisplays), which calls back into Display functions
+ // which require locking.
+ mutable std::recursive_mutex mStateMutex;
+
+ // Allocate RAM able to store all layers and rects used for
+ // communication with HWC1. Place allocated RAM in variable
+ // mHwc1RequestedContents.
+ void allocateRequestedContents();
+
+ // Array of structs exchanged between client and hwc1 device.
+ // Sent to device upon calling prepare().
+ std::unique_ptr<hwc_display_contents_1> mHwc1RequestedContents;
+ private:
+ DeferredFence mRetireFence;
+
+ // Will only be non-null after the Display has been validated and
+ // before it has been presented
+ std::unique_ptr<Changes> mChanges;
+
+ int32_t mHwc1Id;
+
+ std::vector<std::shared_ptr<Config>> mConfigs;
+ std::shared_ptr<const Config> mActiveConfig;
+ std::set<android_color_mode_t> mColorModes;
+ android_color_mode_t mActiveColorMode;
+ std::string mName;
+ HWC2::DisplayType mType;
+ HWC2::PowerMode mPowerMode;
+ HWC2::Vsync mVsyncEnabled;
+
+ // Used to populate HWC1 HWC_FRAMEBUFFER_TARGET layer
+ FencedBuffer mClientTarget;
+
+
+ FencedBuffer mOutputBuffer;
+
+ bool mHasColorTransform;
+
+ // All layers this Display is aware of.
+ std::multiset<std::shared_ptr<Layer>, SortLayersByZ> mLayers;
+
+ // Mapping between layer index in array of hwc_display_contents_1*
+ // passed to HWC1 during validate/set and Layer object.
+ std::unordered_map<size_t, std::shared_ptr<Layer>> mHwc1LayerMap;
+
+ // All communication with HWC1 via prepare/set is done with one
+ // alloc. This pointer is pointing to a pool of hwc_rect_t.
+ size_t mNumAvailableRects;
+ hwc_rect_t* mNextAvailableRect;
+
+ // True if any of the Layers contained in this Display have been
+ // updated with anything other than a buffer since last call to
+ // Display::set()
+ bool mGeometryChanged;
+ };
+
+ // Utility template calling a Display object method directly based on the
+ // hwc2_display_t displayId parameter.
+ template <typename ...Args>
+ static int32_t callDisplayFunction(hwc2_device_t* device,
+ hwc2_display_t displayId, HWC2::Error (Display::*member)(Args...),
+ Args... args) {
+ auto display = getAdapter(device)->getDisplay(displayId);
+ if (!display) {
+ return static_cast<int32_t>(HWC2::Error::BadDisplay);
+ }
+ auto error = ((*display).*member)(std::forward<Args>(args)...);
+ return static_cast<int32_t>(error);
+ }
+
+ template <typename MF, MF memFunc, typename ...Args>
+ static int32_t displayHook(hwc2_device_t* device, hwc2_display_t displayId,
+ Args... args) {
+ return HWC2On1Adapter::callDisplayFunction(device, displayId, memFunc,
+ std::forward<Args>(args)...);
+ }
+
+ static int32_t getDisplayAttributeHook(hwc2_device_t* device,
+ hwc2_display_t display, hwc2_config_t config,
+ int32_t intAttribute, int32_t* outValue) {
+ auto attribute = static_cast<HWC2::Attribute>(intAttribute);
+ return callDisplayFunction(device, display, &Display::getAttribute,
+ config, attribute, outValue);
+ }
+
+ static int32_t setColorTransformHook(hwc2_device_t* device,
+ hwc2_display_t display, const float* /*matrix*/,
+ int32_t /*android_color_transform_t*/ intHint) {
+ // We intentionally throw away the matrix, because if the hint is
+ // anything other than IDENTITY, we have to fall back to client
+ // composition anyway
+ auto hint = static_cast<android_color_transform_t>(intHint);
+ return callDisplayFunction(device, display, &Display::setColorTransform,
+ hint);
+ }
+
+ static int32_t setColorModeHook(hwc2_device_t* device,
+ hwc2_display_t display, int32_t /*android_color_mode_t*/ intMode) {
+ auto mode = static_cast<android_color_mode_t>(intMode);
+ return callDisplayFunction(device, display, &Display::setColorMode,
+ mode);
+ }
+
+ static int32_t setPowerModeHook(hwc2_device_t* device,
+ hwc2_display_t display, int32_t intMode) {
+ auto mode = static_cast<HWC2::PowerMode>(intMode);
+ return callDisplayFunction(device, display, &Display::setPowerMode,
+ mode);
+ }
+
+ static int32_t setVsyncEnabledHook(hwc2_device_t* device,
+ hwc2_display_t display, int32_t intEnabled) {
+ auto enabled = static_cast<HWC2::Vsync>(intEnabled);
+ return callDisplayFunction(device, display, &Display::setVsyncEnabled,
+ enabled);
+ }
+
+ class Layer {
+ public:
+ explicit Layer(Display& display);
+
+ bool operator==(const Layer& other) { return mId == other.mId; }
+ bool operator!=(const Layer& other) { return !(*this == other); }
+
+ hwc2_layer_t getId() const { return mId; }
+ Display& getDisplay() const { return mDisplay; }
+
+ // HWC2 Layer functions
+ HWC2::Error setBuffer(buffer_handle_t buffer, int32_t acquireFence);
+ HWC2::Error setCursorPosition(int32_t x, int32_t y);
+ HWC2::Error setSurfaceDamage(hwc_region_t damage);
+
+ // HWC2 Layer state functions
+ HWC2::Error setBlendMode(HWC2::BlendMode mode);
+ HWC2::Error setColor(hwc_color_t color);
+ HWC2::Error setCompositionType(HWC2::Composition type);
+ HWC2::Error setDataspace(android_dataspace_t dataspace);
+ HWC2::Error setDisplayFrame(hwc_rect_t frame);
+ HWC2::Error setPlaneAlpha(float alpha);
+ HWC2::Error setSidebandStream(const native_handle_t* stream);
+ HWC2::Error setSourceCrop(hwc_frect_t crop);
+ HWC2::Error setTransform(HWC2::Transform transform);
+ HWC2::Error setVisibleRegion(hwc_region_t visible);
+ HWC2::Error setZ(uint32_t z);
+
+ HWC2::Composition getCompositionType() const {
+ return mCompositionType;
+ }
+ uint32_t getZ() const { return mZ; }
+
+ void addReleaseFence(int fenceFd);
+ const sp<MiniFence>& getReleaseFence() const;
+
+ void setHwc1Id(size_t id) { mHwc1Id = id; }
+ size_t getHwc1Id() const { return mHwc1Id; }
+
+ // Write state to HWC1 communication struct.
+ void applyState(struct hwc_layer_1& hwc1Layer);
+
+ std::string dump() const;
+
+ std::size_t getNumVisibleRegions() { return mVisibleRegion.size(); }
+
+ std::size_t getNumSurfaceDamages() { return mSurfaceDamage.size(); }
+
+ // True if a layer cannot be properly rendered by the device due
+ // to usage of SolidColor (a.k.a BackgroundColor in HWC1).
+ bool hasUnsupportedBackgroundColor() {
+ return (mCompositionType == HWC2::Composition::SolidColor &&
+ !mDisplay.getDevice().supportsBackgroundColor());
+ }
+ private:
+ void applyCommonState(struct hwc_layer_1& hwc1Layer);
+ void applySolidColorState(struct hwc_layer_1& hwc1Layer);
+ void applySidebandState(struct hwc_layer_1& hwc1Layer);
+ void applyBufferState(struct hwc_layer_1& hwc1Layer);
+ void applyCompositionType(struct hwc_layer_1& hwc1Layer);
+
+ static std::atomic<hwc2_layer_t> sNextId;
+ const hwc2_layer_t mId;
+ Display& mDisplay;
+
+ FencedBuffer mBuffer;
+ std::vector<hwc_rect_t> mSurfaceDamage;
+
+ HWC2::BlendMode mBlendMode;
+ hwc_color_t mColor;
+ HWC2::Composition mCompositionType;
+ hwc_rect_t mDisplayFrame;
+ float mPlaneAlpha;
+ const native_handle_t* mSidebandStream;
+ hwc_frect_t mSourceCrop;
+ HWC2::Transform mTransform;
+ std::vector<hwc_rect_t> mVisibleRegion;
+
+ uint32_t mZ;
+
+ DeferredFence mReleaseFence;
+
+ size_t mHwc1Id;
+ bool mHasUnsupportedPlaneAlpha;
+ };
+
+ // Utility tempate calling a Layer object method based on ID parameters:
+ // hwc2_display_t displayId
+ // and
+ // hwc2_layer_t layerId
+ template <typename ...Args>
+ static int32_t callLayerFunction(hwc2_device_t* device,
+ hwc2_display_t displayId, hwc2_layer_t layerId,
+ HWC2::Error (Layer::*member)(Args...), Args... args) {
+ auto result = getAdapter(device)->getLayer(displayId, layerId);
+ auto error = std::get<HWC2::Error>(result);
+ if (error == HWC2::Error::None) {
+ auto layer = std::get<Layer*>(result);
+ error = ((*layer).*member)(std::forward<Args>(args)...);
+ }
+ return static_cast<int32_t>(error);
+ }
+
+ template <typename MF, MF memFunc, typename ...Args>
+ static int32_t layerHook(hwc2_device_t* device, hwc2_display_t displayId,
+ hwc2_layer_t layerId, Args... args) {
+ return HWC2On1Adapter::callLayerFunction(device, displayId, layerId,
+ memFunc, std::forward<Args>(args)...);
+ }
+
+ // Layer state functions
+
+ static int32_t setLayerBlendModeHook(hwc2_device_t* device,
+ hwc2_display_t display, hwc2_layer_t layer, int32_t intMode) {
+ auto mode = static_cast<HWC2::BlendMode>(intMode);
+ return callLayerFunction(device, display, layer,
+ &Layer::setBlendMode, mode);
+ }
+
+ static int32_t setLayerCompositionTypeHook(hwc2_device_t* device,
+ hwc2_display_t display, hwc2_layer_t layer, int32_t intType) {
+ auto type = static_cast<HWC2::Composition>(intType);
+ return callLayerFunction(device, display, layer,
+ &Layer::setCompositionType, type);
+ }
+
+ static int32_t setLayerDataspaceHook(hwc2_device_t* device,
+ hwc2_display_t display, hwc2_layer_t layer, int32_t intDataspace) {
+ auto dataspace = static_cast<android_dataspace_t>(intDataspace);
+ return callLayerFunction(device, display, layer, &Layer::setDataspace,
+ dataspace);
+ }
+
+ static int32_t setLayerTransformHook(hwc2_device_t* device,
+ hwc2_display_t display, hwc2_layer_t layer, int32_t intTransform) {
+ auto transform = static_cast<HWC2::Transform>(intTransform);
+ return callLayerFunction(device, display, layer, &Layer::setTransform,
+ transform);
+ }
+
+ static int32_t setLayerZOrderHook(hwc2_device_t* device,
+ hwc2_display_t display, hwc2_layer_t layer, uint32_t z) {
+ return callDisplayFunction(device, display, &Display::updateLayerZ,
+ layer, z);
+ }
+
+ // Adapter internals
+
+ void populateCapabilities();
+ Display* getDisplay(hwc2_display_t id);
+ std::tuple<Layer*, HWC2::Error> getLayer(hwc2_display_t displayId,
+ hwc2_layer_t layerId);
+ void populatePrimary();
+
+ bool prepareAllDisplays();
+ std::vector<struct hwc_display_contents_1*> mHwc1Contents;
+ HWC2::Error setAllDisplays();
+
+ // Callbacks
+ void hwc1Invalidate();
+ void hwc1Vsync(int hwc1DisplayId, int64_t timestamp);
+ void hwc1Hotplug(int hwc1DisplayId, int connected);
+
+ // These are set in the constructor and before any asynchronous events are
+ // possible
+
+ struct hwc_composer_device_1* const mHwc1Device;
+ const uint8_t mHwc1MinorVersion;
+ bool mHwc1SupportsVirtualDisplays;
+ bool mHwc1SupportsBackgroundColor;
+
+ class Callbacks;
+ const std::unique_ptr<Callbacks> mHwc1Callbacks;
+
+ std::unordered_set<HWC2::Capability> mCapabilities;
+
+ // These are only accessed from the main SurfaceFlinger thread (not from
+ // callbacks or dump
+
+ std::map<hwc2_layer_t, std::shared_ptr<Layer>> mLayers;
+
+ // A HWC1 supports only one virtual display.
+ std::shared_ptr<Display> mHwc1VirtualDisplay;
+
+ // These are potentially accessed from multiple threads, and are protected
+ // by this mutex. This needs to be recursive, since the HWC1 implementation
+ // can call back into the invalidate callback on the same thread that is
+ // calling prepare.
+ std::recursive_timed_mutex mStateMutex;
+
+ struct CallbackInfo {
+ hwc2_callback_data_t data;
+ hwc2_function_pointer_t pointer;
+ };
+ std::unordered_map<HWC2::Callback, CallbackInfo> mCallbacks;
+ bool mHasPendingInvalidate;
+
+ // There is a small gap between the time the HWC1 module is started and
+ // when the callbacks for vsync and hotplugs are registered by the
+ // HWC2on1Adapter. To prevent losing events they are stored in these arrays
+ // and fed to the callback as soon as possible.
+ std::vector<std::pair<int, int64_t>> mPendingVsyncs;
+ std::vector<std::pair<int, int>> mPendingHotplugs;
+
+ // Mapping between HWC1 display id and Display objects.
+ std::map<hwc2_display_t, std::shared_ptr<Display>> mDisplays;
+
+ // Map HWC1 display type (HWC_DISPLAY_PRIMARY, HWC_DISPLAY_EXTERNAL,
+ // HWC_DISPLAY_VIRTUAL) to Display IDs generated by HWC2on1Adapter objects.
+ std::unordered_map<int, hwc2_display_t> mHwc1DisplayMap;
+};
+
+} // namespace android
+
+#endif
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/MiniFence.h b/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/MiniFence.h
new file mode 100644
index 0000000..75de764
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/MiniFence.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MINIFENCE_H
+#define MINIFENCE_H
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+/* MiniFence is a minimal re-implementation of Fence from libui. It exists to
+ * avoid linking the HWC2on1Adapter to libui and satisfy Treble requirements.
+ */
+class MiniFence : public LightRefBase<MiniFence> {
+public:
+ static const sp<MiniFence> NO_FENCE;
+
+ // Construct a new MiniFence object with an invalid file descriptor.
+ MiniFence();
+
+ // Construct a new MiniFence object to manage a given fence file descriptor.
+ // When the new MiniFence object is destructed the file descriptor will be
+ // closed.
+ explicit MiniFence(int fenceFd);
+
+ // Not copyable or movable.
+ MiniFence(const MiniFence& rhs) = delete;
+ MiniFence& operator=(const MiniFence& rhs) = delete;
+ MiniFence(MiniFence&& rhs) = delete;
+ MiniFence& operator=(MiniFence&& rhs) = delete;
+
+ // Return a duplicate of the fence file descriptor. The caller is
+ // responsible for closing the returned file descriptor. On error, -1 will
+ // be returned and errno will indicate the problem.
+ int dup() const;
+
+private:
+ // Only allow instantiation using ref counting.
+ friend class LightRefBase<MiniFence>;
+ ~MiniFence();
+
+ int mFenceFd;
+
+};
+}
+#endif //MINIFENCE_H
diff --git a/graphics/composer/2.1/utils/hwc2onfbadapter/Android.bp b/graphics/composer/2.1/utils/hwc2onfbadapter/Android.bp
new file mode 100644
index 0000000..73a41f7
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2onfbadapter/Android.bp
@@ -0,0 +1,33 @@
+// Copyright 2010 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_shared {
+ name: "libhwc2onfbadapter",
+ vendor: true,
+
+ clang: true,
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+
+ srcs: [
+ "HWC2OnFbAdapter.cpp",
+ ],
+
+ header_libs: ["libhardware_headers"],
+ shared_libs: ["liblog", "libsync"],
+ export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.1/utils/hwc2onfbadapter/HWC2OnFbAdapter.cpp b/graphics/composer/2.1/utils/hwc2onfbadapter/HWC2OnFbAdapter.cpp
new file mode 100644
index 0000000..7c9e651
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2onfbadapter/HWC2OnFbAdapter.cpp
@@ -0,0 +1,887 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#define LOG_TAG "HWC2OnFbAdapter"
+
+//#define LOG_NDEBUG 0
+
+#include "hwc2onfbadapter/HWC2OnFbAdapter.h"
+
+#include <algorithm>
+#include <type_traits>
+
+#include <inttypes.h>
+#include <time.h>
+#include <sys/prctl.h>
+#include <unistd.h> // for close
+
+#include <hardware/fb.h>
+#include <log/log.h>
+#include <sync/sync.h>
+
+namespace android {
+
+namespace {
+
+void dumpHook(hwc2_device_t* device, uint32_t* outSize, char* outBuffer) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (outBuffer) {
+ *outSize = adapter.getDebugString().copy(outBuffer, *outSize);
+ } else {
+ adapter.updateDebugString();
+ *outSize = adapter.getDebugString().size();
+ }
+}
+
+int32_t registerCallbackHook(hwc2_device_t* device, int32_t descriptor,
+ hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ switch (descriptor) {
+ case HWC2_CALLBACK_HOTPLUG:
+ if (pointer) {
+ reinterpret_cast<HWC2_PFN_HOTPLUG>(pointer)(callbackData, adapter.getDisplayId(),
+ HWC2_CONNECTION_CONNECTED);
+ }
+ break;
+ case HWC2_CALLBACK_REFRESH:
+ break;
+ case HWC2_CALLBACK_VSYNC:
+ adapter.setVsyncCallback(reinterpret_cast<HWC2_PFN_VSYNC>(pointer), callbackData);
+ break;
+ default:
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ return HWC2_ERROR_NONE;
+}
+
+uint32_t getMaxVirtualDisplayCountHook(hwc2_device_t* /*device*/) {
+ return 0;
+}
+
+int32_t createVirtualDisplayHook(hwc2_device_t* /*device*/, uint32_t /*width*/, uint32_t /*height*/,
+ int32_t* /*format*/, hwc2_display_t* /*outDisplay*/) {
+ return HWC2_ERROR_NO_RESOURCES;
+}
+
+int32_t destroyVirtualDisplayHook(hwc2_device_t* /*device*/, hwc2_display_t /*display*/) {
+ return HWC2_ERROR_BAD_DISPLAY;
+}
+
+int32_t setOutputBufferHook(hwc2_device_t* /*device*/, hwc2_display_t /*display*/,
+ buffer_handle_t /*buffer*/, int32_t /*releaseFence*/) {
+ return HWC2_ERROR_BAD_DISPLAY;
+}
+
+int32_t getDisplayNameHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outSize,
+ char* outName) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ const auto& info = adapter.getInfo();
+ if (outName) {
+ *outSize = info.name.copy(outName, *outSize);
+ } else {
+ *outSize = info.name.size();
+ }
+
+ return HWC2_ERROR_NONE;
+}
+
+int32_t getDisplayTypeHook(hwc2_device_t* device, hwc2_display_t display, int32_t* outType) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ *outType = HWC2_DISPLAY_TYPE_PHYSICAL;
+ return HWC2_ERROR_NONE;
+}
+
+int32_t getDozeSupportHook(hwc2_device_t* device, hwc2_display_t display, int32_t* outSupport) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ *outSupport = 0;
+ return HWC2_ERROR_NONE;
+}
+
+int32_t getHdrCapabilitiesHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumTypes,
+ int32_t* /*outTypes*/, float* /*outMaxLuminance*/,
+ float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ *outNumTypes = 0;
+ return HWC2_ERROR_NONE;
+}
+
+int32_t setPowerModeHook(hwc2_device_t* device, hwc2_display_t display, int32_t /*mode*/) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ // pretend that it works
+ return HWC2_ERROR_NONE;
+}
+
+int32_t setVsyncEnabledHook(hwc2_device_t* device, hwc2_display_t display, int32_t enabled) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ adapter.enableVsync(enabled == HWC2_VSYNC_ENABLE);
+ return HWC2_ERROR_NONE;
+}
+
+int32_t getColorModesHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumModes,
+ int32_t* outModes) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ if (outModes) {
+ if (*outNumModes > 0) {
+ outModes[0] = HAL_COLOR_MODE_NATIVE;
+ *outNumModes = 1;
+ }
+ } else {
+ *outNumModes = 1;
+ }
+
+ return HWC2_ERROR_NONE;
+}
+
+int32_t setColorModeHook(hwc2_device_t* device, hwc2_display_t display, int32_t mode) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (mode != HAL_COLOR_MODE_NATIVE) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ return HWC2_ERROR_NONE;
+}
+
+int32_t setColorTransformHook(hwc2_device_t* device, hwc2_display_t display,
+ const float* /*matrix*/, int32_t /*hint*/) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ // we always force client composition
+ adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+ return HWC2_ERROR_NONE;
+}
+
+int32_t getClientTargetSupportHook(hwc2_device_t* device, hwc2_display_t display, uint32_t width,
+ uint32_t height, int32_t format, int32_t dataspace) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (dataspace != HAL_DATASPACE_UNKNOWN) {
+ return HWC2_ERROR_UNSUPPORTED;
+ }
+
+ const auto& info = adapter.getInfo();
+ return (info.width == width && info.height == height && info.format == format)
+ ? HWC2_ERROR_NONE
+ : HWC2_ERROR_UNSUPPORTED;
+}
+
+int32_t setClientTargetHook(hwc2_device_t* device, hwc2_display_t display, buffer_handle_t target,
+ int32_t acquireFence, int32_t dataspace, hwc_region_t /*damage*/) {
+ if (acquireFence >= 0) {
+ sync_wait(acquireFence, -1);
+ close(acquireFence);
+ }
+
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (dataspace != HAL_DATASPACE_UNKNOWN) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ // no state change
+ adapter.setBuffer(target);
+ return HWC2_ERROR_NONE;
+}
+
+int32_t getDisplayConfigsHook(hwc2_device_t* device, hwc2_display_t display,
+ uint32_t* outNumConfigs, hwc2_config_t* outConfigs) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ if (outConfigs) {
+ if (*outNumConfigs > 0) {
+ outConfigs[0] = adapter.getConfigId();
+ *outNumConfigs = 1;
+ }
+ } else {
+ *outNumConfigs = 1;
+ }
+
+ return HWC2_ERROR_NONE;
+}
+
+int32_t getDisplayAttributeHook(hwc2_device_t* device, hwc2_display_t display, hwc2_config_t config,
+ int32_t attribute, int32_t* outValue) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (adapter.getConfigId() != config) {
+ return HWC2_ERROR_BAD_CONFIG;
+ }
+
+ const auto& info = adapter.getInfo();
+ switch (attribute) {
+ case HWC2_ATTRIBUTE_WIDTH:
+ *outValue = int32_t(info.width);
+ break;
+ case HWC2_ATTRIBUTE_HEIGHT:
+ *outValue = int32_t(info.height);
+ break;
+ case HWC2_ATTRIBUTE_VSYNC_PERIOD:
+ *outValue = int32_t(info.vsync_period_ns);
+ break;
+ case HWC2_ATTRIBUTE_DPI_X:
+ *outValue = int32_t(info.xdpi_scaled);
+ break;
+ case HWC2_ATTRIBUTE_DPI_Y:
+ *outValue = int32_t(info.ydpi_scaled);
+ break;
+ default:
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ return HWC2_ERROR_NONE;
+}
+
+int32_t getActiveConfigHook(hwc2_device_t* device, hwc2_display_t display,
+ hwc2_config_t* outConfig) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ *outConfig = adapter.getConfigId();
+ return HWC2_ERROR_NONE;
+}
+
+int32_t setActiveConfigHook(hwc2_device_t* device, hwc2_display_t display, hwc2_config_t config) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (adapter.getConfigId() != config) {
+ return HWC2_ERROR_BAD_CONFIG;
+ }
+
+ return HWC2_ERROR_NONE;
+}
+
+int32_t validateDisplayHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumTypes,
+ uint32_t* outNumRequests) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ const auto& dirtyLayers = adapter.getDirtyLayers();
+ *outNumTypes = dirtyLayers.size();
+ *outNumRequests = 0;
+
+ if (*outNumTypes > 0) {
+ adapter.setState(HWC2OnFbAdapter::State::VALIDATED_WITH_CHANGES);
+ return HWC2_ERROR_HAS_CHANGES;
+ } else {
+ adapter.setState(HWC2OnFbAdapter::State::VALIDATED);
+ return HWC2_ERROR_NONE;
+ }
+}
+
+int32_t getChangedCompositionTypesHook(hwc2_device_t* device, hwc2_display_t display,
+ uint32_t* outNumElements, hwc2_layer_t* outLayers,
+ int32_t* outTypes) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (adapter.getState() == HWC2OnFbAdapter::State::MODIFIED) {
+ return HWC2_ERROR_NOT_VALIDATED;
+ }
+
+ // request client composition for all layers
+ const auto& dirtyLayers = adapter.getDirtyLayers();
+ if (outLayers && outTypes) {
+ *outNumElements = std::min(*outNumElements, uint32_t(dirtyLayers.size()));
+ auto iter = dirtyLayers.cbegin();
+ for (uint32_t i = 0; i < *outNumElements; i++) {
+ outLayers[i] = *iter++;
+ outTypes[i] = HWC2_COMPOSITION_CLIENT;
+ }
+ } else {
+ *outNumElements = dirtyLayers.size();
+ }
+
+ return HWC2_ERROR_NONE;
+}
+
+int32_t getDisplayRequestsHook(hwc2_device_t* device, hwc2_display_t display,
+ int32_t* outDisplayRequests, uint32_t* outNumElements,
+ hwc2_layer_t* /*outLayers*/, int32_t* /*outLayerRequests*/) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (adapter.getState() == HWC2OnFbAdapter::State::MODIFIED) {
+ return HWC2_ERROR_NOT_VALIDATED;
+ }
+
+ *outDisplayRequests = 0;
+ *outNumElements = 0;
+ return HWC2_ERROR_NONE;
+}
+
+int32_t acceptDisplayChangesHook(hwc2_device_t* device, hwc2_display_t display) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (adapter.getState() == HWC2OnFbAdapter::State::MODIFIED) {
+ return HWC2_ERROR_NOT_VALIDATED;
+ }
+
+ adapter.clearDirtyLayers();
+ adapter.setState(HWC2OnFbAdapter::State::VALIDATED);
+ return HWC2_ERROR_NONE;
+}
+
+int32_t presentDisplayHook(hwc2_device_t* device, hwc2_display_t display,
+ int32_t* outPresentFence) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (adapter.getState() != HWC2OnFbAdapter::State::VALIDATED) {
+ return HWC2_ERROR_NOT_VALIDATED;
+ }
+
+ adapter.postBuffer();
+ *outPresentFence = -1;
+
+ return HWC2_ERROR_NONE;
+}
+
+int32_t getReleaseFencesHook(hwc2_device_t* device, hwc2_display_t display,
+ uint32_t* outNumElements, hwc2_layer_t* /*outLayers*/,
+ int32_t* /*outFences*/) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ *outNumElements = 0;
+ return HWC2_ERROR_NONE;
+}
+
+int32_t createLayerHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t* outLayer) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ *outLayer = adapter.addLayer();
+ adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+ return HWC2_ERROR_NONE;
+}
+
+int32_t destroyLayerHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ if (adapter.removeLayer(layer)) {
+ adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+ return HWC2_ERROR_NONE;
+ } else {
+ return HWC2_ERROR_BAD_LAYER;
+ }
+}
+
+int32_t setCursorPositionHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t /*layer*/,
+ int32_t /*x*/, int32_t /*y*/) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ // always an error
+ return HWC2_ERROR_BAD_LAYER;
+}
+
+int32_t setLayerBufferHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+ buffer_handle_t /*buffer*/, int32_t acquireFence) {
+ if (acquireFence >= 0) {
+ sync_wait(acquireFence, -1);
+ close(acquireFence);
+ }
+
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (!adapter.hasLayer(layer)) {
+ return HWC2_ERROR_BAD_LAYER;
+ }
+
+ // no state change
+ return HWC2_ERROR_NONE;
+}
+
+int32_t setLayerSurfaceDamageHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+ hwc_region_t /*damage*/) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (!adapter.hasLayer(layer)) {
+ return HWC2_ERROR_BAD_LAYER;
+ }
+
+ // no state change
+ return HWC2_ERROR_NONE;
+}
+
+int32_t setLayerCompositionTypeHook(hwc2_device_t* device, hwc2_display_t display,
+ hwc2_layer_t layer, int32_t type) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (!adapter.markLayerDirty(layer, type != HWC2_COMPOSITION_CLIENT)) {
+ return HWC2_ERROR_BAD_LAYER;
+ }
+
+ adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+ return HWC2_ERROR_NONE;
+}
+
+template <typename... Args>
+int32_t setLayerStateHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+ Args... /*args*/) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (!adapter.hasLayer(layer)) {
+ return HWC2_ERROR_BAD_LAYER;
+ }
+
+ adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+ return HWC2_ERROR_NONE;
+}
+
+template <typename PFN, typename T>
+static hwc2_function_pointer_t asFP(T function) {
+ static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
+ return reinterpret_cast<hwc2_function_pointer_t>(function);
+}
+
+hwc2_function_pointer_t getFunctionHook(hwc2_device_t* /*device*/, int32_t descriptor) {
+ switch (descriptor) {
+ // global functions
+ case HWC2_FUNCTION_DUMP:
+ return asFP<HWC2_PFN_DUMP>(dumpHook);
+ case HWC2_FUNCTION_REGISTER_CALLBACK:
+ return asFP<HWC2_PFN_REGISTER_CALLBACK>(registerCallbackHook);
+
+ // virtual display functions
+ case HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT:
+ return asFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(getMaxVirtualDisplayCountHook);
+ case HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY:
+ return asFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(createVirtualDisplayHook);
+ case HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY:
+ return asFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(destroyVirtualDisplayHook);
+ case HWC2_FUNCTION_SET_OUTPUT_BUFFER:
+ return asFP<HWC2_PFN_SET_OUTPUT_BUFFER>(setOutputBufferHook);
+
+ // display functions
+ case HWC2_FUNCTION_GET_DISPLAY_NAME:
+ return asFP<HWC2_PFN_GET_DISPLAY_NAME>(getDisplayNameHook);
+ case HWC2_FUNCTION_GET_DISPLAY_TYPE:
+ return asFP<HWC2_PFN_GET_DISPLAY_TYPE>(getDisplayTypeHook);
+ case HWC2_FUNCTION_GET_DOZE_SUPPORT:
+ return asFP<HWC2_PFN_GET_DOZE_SUPPORT>(getDozeSupportHook);
+ case HWC2_FUNCTION_GET_HDR_CAPABILITIES:
+ return asFP<HWC2_PFN_GET_HDR_CAPABILITIES>(getHdrCapabilitiesHook);
+ case HWC2_FUNCTION_SET_POWER_MODE:
+ return asFP<HWC2_PFN_SET_POWER_MODE>(setPowerModeHook);
+ case HWC2_FUNCTION_SET_VSYNC_ENABLED:
+ return asFP<HWC2_PFN_SET_VSYNC_ENABLED>(setVsyncEnabledHook);
+ case HWC2_FUNCTION_GET_COLOR_MODES:
+ return asFP<HWC2_PFN_GET_COLOR_MODES>(getColorModesHook);
+ case HWC2_FUNCTION_SET_COLOR_MODE:
+ return asFP<HWC2_PFN_SET_COLOR_MODE>(setColorModeHook);
+ case HWC2_FUNCTION_SET_COLOR_TRANSFORM:
+ return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(setColorTransformHook);
+ case HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT:
+ return asFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(getClientTargetSupportHook);
+ case HWC2_FUNCTION_SET_CLIENT_TARGET:
+ return asFP<HWC2_PFN_SET_CLIENT_TARGET>(setClientTargetHook);
+
+ // config functions
+ case HWC2_FUNCTION_GET_DISPLAY_CONFIGS:
+ return asFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(getDisplayConfigsHook);
+ case HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE:
+ return asFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(getDisplayAttributeHook);
+ case HWC2_FUNCTION_GET_ACTIVE_CONFIG:
+ return asFP<HWC2_PFN_GET_ACTIVE_CONFIG>(getActiveConfigHook);
+ case HWC2_FUNCTION_SET_ACTIVE_CONFIG:
+ return asFP<HWC2_PFN_SET_ACTIVE_CONFIG>(setActiveConfigHook);
+
+ // validate/present functions
+ case HWC2_FUNCTION_VALIDATE_DISPLAY:
+ return asFP<HWC2_PFN_VALIDATE_DISPLAY>(validateDisplayHook);
+ case HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES:
+ return asFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(getChangedCompositionTypesHook);
+ case HWC2_FUNCTION_GET_DISPLAY_REQUESTS:
+ return asFP<HWC2_PFN_GET_DISPLAY_REQUESTS>(getDisplayRequestsHook);
+ case HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES:
+ return asFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(acceptDisplayChangesHook);
+ case HWC2_FUNCTION_PRESENT_DISPLAY:
+ return asFP<HWC2_PFN_PRESENT_DISPLAY>(presentDisplayHook);
+ case HWC2_FUNCTION_GET_RELEASE_FENCES:
+ return asFP<HWC2_PFN_GET_RELEASE_FENCES>(getReleaseFencesHook);
+
+ // layer create/destroy
+ case HWC2_FUNCTION_CREATE_LAYER:
+ return asFP<HWC2_PFN_CREATE_LAYER>(createLayerHook);
+ case HWC2_FUNCTION_DESTROY_LAYER:
+ return asFP<HWC2_PFN_DESTROY_LAYER>(destroyLayerHook);
+
+ // layer functions; validateDisplay not required
+ case HWC2_FUNCTION_SET_CURSOR_POSITION:
+ return asFP<HWC2_PFN_SET_CURSOR_POSITION>(setCursorPositionHook);
+ case HWC2_FUNCTION_SET_LAYER_BUFFER:
+ return asFP<HWC2_PFN_SET_LAYER_BUFFER>(setLayerBufferHook);
+ case HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE:
+ return asFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(setLayerSurfaceDamageHook);
+
+ // layer state functions; validateDisplay required
+ case HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE:
+ return asFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(setLayerCompositionTypeHook);
+ case HWC2_FUNCTION_SET_LAYER_BLEND_MODE:
+ return asFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(setLayerStateHook<int32_t>);
+ case HWC2_FUNCTION_SET_LAYER_COLOR:
+ return asFP<HWC2_PFN_SET_LAYER_COLOR>(setLayerStateHook<hwc_color_t>);
+ case HWC2_FUNCTION_SET_LAYER_DATASPACE:
+ return asFP<HWC2_PFN_SET_LAYER_DATASPACE>(setLayerStateHook<int32_t>);
+ case HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME:
+ return asFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(setLayerStateHook<hwc_rect_t>);
+ case HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA:
+ return asFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(setLayerStateHook<float>);
+ case HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM:
+ return asFP<HWC2_PFN_SET_LAYER_SIDEBAND_STREAM>(setLayerStateHook<buffer_handle_t>);
+ case HWC2_FUNCTION_SET_LAYER_SOURCE_CROP:
+ return asFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(setLayerStateHook<hwc_frect_t>);
+ case HWC2_FUNCTION_SET_LAYER_TRANSFORM:
+ return asFP<HWC2_PFN_SET_LAYER_TRANSFORM>(setLayerStateHook<int32_t>);
+ case HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION:
+ return asFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(setLayerStateHook<hwc_region_t>);
+ case HWC2_FUNCTION_SET_LAYER_Z_ORDER:
+ return asFP<HWC2_PFN_SET_LAYER_Z_ORDER>(setLayerStateHook<uint32_t>);
+
+ default:
+ ALOGE("unknown function descriptor %d", descriptor);
+ return nullptr;
+ }
+}
+
+void getCapabilitiesHook(hwc2_device_t* /*device*/, uint32_t* outCount,
+ int32_t* /*outCapabilities*/) {
+ *outCount = 0;
+}
+
+int closeHook(hw_device_t* device) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ adapter.close();
+ return 0;
+}
+
+} // anonymous namespace
+
+HWC2OnFbAdapter::HWC2OnFbAdapter(framebuffer_device_t* fbDevice)
+ : hwc2_device_t(), mFbDevice(fbDevice) {
+ common.close = closeHook;
+ hwc2_device::getCapabilities = getCapabilitiesHook;
+ hwc2_device::getFunction = getFunctionHook;
+
+ mFbInfo.name = "fbdev";
+ mFbInfo.width = mFbDevice->width;
+ mFbInfo.height = mFbDevice->height;
+ mFbInfo.format = mFbDevice->format;
+ mFbInfo.vsync_period_ns = int(1e9 / mFbDevice->fps);
+ mFbInfo.xdpi_scaled = int(mFbDevice->xdpi * 1000.0f);
+ mFbInfo.ydpi_scaled = int(mFbDevice->ydpi * 1000.0f);
+
+ mVsyncThread.start(0, mFbInfo.vsync_period_ns);
+}
+
+HWC2OnFbAdapter& HWC2OnFbAdapter::cast(hw_device_t* device) {
+ return *reinterpret_cast<HWC2OnFbAdapter*>(device);
+}
+
+HWC2OnFbAdapter& HWC2OnFbAdapter::cast(hwc2_device_t* device) {
+ return *reinterpret_cast<HWC2OnFbAdapter*>(device);
+}
+
+hwc2_display_t HWC2OnFbAdapter::getDisplayId() {
+ return 0;
+}
+
+hwc2_config_t HWC2OnFbAdapter::getConfigId() {
+ return 0;
+}
+
+void HWC2OnFbAdapter::close() {
+ mVsyncThread.stop();
+ framebuffer_close(mFbDevice);
+}
+
+const HWC2OnFbAdapter::Info& HWC2OnFbAdapter::getInfo() const {
+ return mFbInfo;
+}
+
+void HWC2OnFbAdapter::updateDebugString() {
+ if (mFbDevice->common.version >= 1 && mFbDevice->dump) {
+ char buffer[4096];
+ mFbDevice->dump(mFbDevice, buffer, sizeof(buffer));
+ buffer[sizeof(buffer) - 1] = '\0';
+
+ mDebugString = buffer;
+ }
+}
+
+const std::string& HWC2OnFbAdapter::getDebugString() const {
+ return mDebugString;
+}
+
+void HWC2OnFbAdapter::setState(State state) {
+ mState = state;
+}
+
+HWC2OnFbAdapter::State HWC2OnFbAdapter::getState() const {
+ return mState;
+}
+
+hwc2_layer_t HWC2OnFbAdapter::addLayer() {
+ hwc2_layer_t id = ++mNextLayerId;
+
+ mLayers.insert(id);
+ mDirtyLayers.insert(id);
+
+ return id;
+}
+
+bool HWC2OnFbAdapter::removeLayer(hwc2_layer_t layer) {
+ mDirtyLayers.erase(layer);
+ return mLayers.erase(layer);
+}
+
+bool HWC2OnFbAdapter::hasLayer(hwc2_layer_t layer) const {
+ return mLayers.count(layer) > 0;
+}
+
+bool HWC2OnFbAdapter::markLayerDirty(hwc2_layer_t layer, bool dirty) {
+ if (mLayers.count(layer) == 0) {
+ return false;
+ }
+
+ if (dirty) {
+ mDirtyLayers.insert(layer);
+ } else {
+ mDirtyLayers.erase(layer);
+ }
+
+ return true;
+}
+
+const std::unordered_set<hwc2_layer_t>& HWC2OnFbAdapter::getDirtyLayers() const {
+ return mDirtyLayers;
+}
+
+void HWC2OnFbAdapter::clearDirtyLayers() {
+ mDirtyLayers.clear();
+}
+
+/*
+ * For each frame, SurfaceFlinger
+ *
+ * - peforms GLES composition
+ * - calls eglSwapBuffers
+ * - calls setClientTarget, which maps to setBuffer below
+ * - calls presentDisplay, which maps to postBuffer below
+ *
+ * setBuffer should be a good place to call compositionComplete.
+ *
+ * As for post, it
+ *
+ * - schedules the buffer for presentation on the next vsync
+ * - locks the buffer and blocks all other users trying to lock it
+ *
+ * It does not give us a way to return a present fence, and we need to live
+ * with that. The implication is that, when we are double-buffered,
+ * SurfaceFlinger assumes the front buffer is available for rendering again
+ * immediately after the back buffer is posted. The locking semantics
+ * hopefully are strong enough that the rendering will be blocked.
+ */
+void HWC2OnFbAdapter::setBuffer(buffer_handle_t buffer) {
+ if (mFbDevice->compositionComplete) {
+ mFbDevice->compositionComplete(mFbDevice);
+ }
+ mBuffer = buffer;
+}
+
+bool HWC2OnFbAdapter::postBuffer() {
+ int error = 0;
+ if (mBuffer) {
+ error = mFbDevice->post(mFbDevice, mBuffer);
+ }
+
+ return error == 0;
+}
+
+void HWC2OnFbAdapter::setVsyncCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data) {
+ mVsyncThread.setCallback(callback, data);
+}
+
+void HWC2OnFbAdapter::enableVsync(bool enable) {
+ mVsyncThread.enableCallback(enable);
+}
+
+int64_t HWC2OnFbAdapter::VsyncThread::now() {
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ return int64_t(ts.tv_sec) * 1'000'000'000 + ts.tv_nsec;
+}
+
+bool HWC2OnFbAdapter::VsyncThread::sleepUntil(int64_t t) {
+ struct timespec ts;
+ ts.tv_sec = t / 1'000'000'000;
+ ts.tv_nsec = t % 1'000'000'000;
+
+ while (true) {
+ int error = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, nullptr);
+ if (error) {
+ if (error == EINTR) {
+ continue;
+ }
+ return false;
+ } else {
+ return true;
+ }
+ }
+}
+
+void HWC2OnFbAdapter::VsyncThread::start(int64_t firstVsync, int64_t period) {
+ mNextVsync = firstVsync;
+ mPeriod = period;
+ mStarted = true;
+ mThread = std::thread(&VsyncThread::vsyncLoop, this);
+}
+
+void HWC2OnFbAdapter::VsyncThread::stop() {
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mStarted = false;
+ }
+ mCondition.notify_all();
+ mThread.join();
+}
+
+void HWC2OnFbAdapter::VsyncThread::setCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mCallback = callback;
+ mCallbackData = data;
+}
+
+void HWC2OnFbAdapter::VsyncThread::enableCallback(bool enable) {
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mCallbackEnabled = enable;
+ }
+ mCondition.notify_all();
+}
+
+void HWC2OnFbAdapter::VsyncThread::vsyncLoop() {
+ prctl(PR_SET_NAME, "VsyncThread", 0, 0, 0);
+
+ std::unique_lock<std::mutex> lock(mMutex);
+ if (!mStarted) {
+ return;
+ }
+
+ while (true) {
+ if (!mCallbackEnabled) {
+ mCondition.wait(lock, [this] { return mCallbackEnabled || !mStarted; });
+ if (!mStarted) {
+ break;
+ }
+ }
+
+ lock.unlock();
+
+ // adjust mNextVsync if necessary
+ int64_t t = now();
+ if (mNextVsync < t) {
+ int64_t n = (t - mNextVsync + mPeriod - 1) / mPeriod;
+ mNextVsync += mPeriod * n;
+ }
+ bool fire = sleepUntil(mNextVsync);
+
+ lock.lock();
+
+ if (fire) {
+ ALOGV("VsyncThread(%" PRId64 ")", mNextVsync);
+ if (mCallback) {
+ mCallback(mCallbackData, getDisplayId(), mNextVsync);
+ }
+ mNextVsync += mPeriod;
+ }
+ }
+}
+
+} // namespace android
diff --git a/graphics/composer/2.1/utils/hwc2onfbadapter/include/hwc2onfbadapter/HWC2OnFbAdapter.h b/graphics/composer/2.1/utils/hwc2onfbadapter/include/hwc2onfbadapter/HWC2OnFbAdapter.h
new file mode 100644
index 0000000..d6272fd
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2onfbadapter/include/hwc2onfbadapter/HWC2OnFbAdapter.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SF_HWC2_ON_FB_ADAPTER_H
+#define ANDROID_SF_HWC2_ON_FB_ADAPTER_H
+
+#include <condition_variable>
+#include <mutex>
+#include <string>
+#include <thread>
+#include <unordered_set>
+
+#include <hardware/hwcomposer2.h>
+
+struct framebuffer_device_t;
+
+namespace android {
+
+class HWC2OnFbAdapter : public hwc2_device_t {
+public:
+ HWC2OnFbAdapter(framebuffer_device_t* fbDevice);
+
+ static HWC2OnFbAdapter& cast(hw_device_t* device);
+ static HWC2OnFbAdapter& cast(hwc2_device_t* device);
+
+ static hwc2_display_t getDisplayId();
+ static hwc2_config_t getConfigId();
+
+ void close();
+
+ struct Info {
+ std::string name;
+ uint32_t width;
+ uint32_t height;
+ int format;
+ int vsync_period_ns;
+ int xdpi_scaled;
+ int ydpi_scaled;
+ };
+ const Info& getInfo() const;
+
+ void updateDebugString();
+ const std::string& getDebugString() const;
+
+ enum class State {
+ MODIFIED,
+ VALIDATED_WITH_CHANGES,
+ VALIDATED,
+ };
+ void setState(State state);
+ State getState() const;
+
+ hwc2_layer_t addLayer();
+ bool removeLayer(hwc2_layer_t layer);
+ bool hasLayer(hwc2_layer_t layer) const;
+ bool markLayerDirty(hwc2_layer_t layer, bool dirty);
+ const std::unordered_set<hwc2_layer_t>& getDirtyLayers() const;
+ void clearDirtyLayers();
+
+ void setBuffer(buffer_handle_t buffer);
+ bool postBuffer();
+
+ void setVsyncCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data);
+ void enableVsync(bool enable);
+
+private:
+ framebuffer_device_t* mFbDevice{nullptr};
+ Info mFbInfo{};
+
+ std::string mDebugString;
+
+ State mState{State::MODIFIED};
+
+ uint64_t mNextLayerId{0};
+ std::unordered_set<hwc2_layer_t> mLayers;
+ std::unordered_set<hwc2_layer_t> mDirtyLayers;
+
+ buffer_handle_t mBuffer{nullptr};
+
+ class VsyncThread {
+ public:
+ static int64_t now();
+ static bool sleepUntil(int64_t t);
+
+ void start(int64_t first, int64_t period);
+ void stop();
+ void setCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data);
+ void enableCallback(bool enable);
+
+ private:
+ void vsyncLoop();
+ bool waitUntilNextVsync();
+
+ std::thread mThread;
+ int64_t mNextVsync{0};
+ int64_t mPeriod{0};
+
+ std::mutex mMutex;
+ std::condition_variable mCondition;
+ bool mStarted{false};
+ HWC2_PFN_VSYNC mCallback{nullptr};
+ hwc2_callback_data_t mCallbackData{nullptr};
+ bool mCallbackEnabled{false};
+ };
+ VsyncThread mVsyncThread;
+};
+
+} // namespace android
+
+#endif // ANDROID_SF_HWC2_ON_FB_ADAPTER_H
diff --git a/graphics/composer/2.1/utils/passthrough/Android.bp b/graphics/composer/2.1/utils/passthrough/Android.bp
new file mode 100644
index 0000000..4d3c976
--- /dev/null
+++ b/graphics/composer/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/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h
new file mode 100644
index 0000000..964e75b
--- /dev/null
+++ b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h
@@ -0,0 +1,670 @@
+/*
+ * 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 {
+ mMustValidateDisplay = true;
+ 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);
+ 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 {
+ uint32_t typesCount = 0;
+ uint32_t reqsCount = 0;
+ int32_t err = mDispatch.validateDisplay(mDevice, display, &typesCount, &reqsCount);
+ mMustValidateDisplay = false;
+
+ if (err != HWC2_ERROR_NONE && err != HWC2_ERROR_HAS_CHANGES) {
+ return static_cast<Error>(err);
+ }
+
+ err = mDispatch.getChangedCompositionTypes(mDevice, 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 = mDispatch.getChangedCompositionTypes(
+ mDevice, display, &typesCount, changedLayers.data(),
+ reinterpret_cast<std::underlying_type<IComposerClient::Composition>::type*>(
+ 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 {
+ if (mMustValidateDisplay) {
+ return Error::NOT_VALIDATED;
+ }
+
+ *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;
+ }
+
+ 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->mMustValidateDisplay = true;
+ 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);
+ }
+
+ 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;
+
+ std::atomic<bool> mMustValidateDisplay{true};
+};
+
+} // namespace detail
+
+using HwcHal = detail::HwcHalImpl<hal::ComposerHal>;
+
+} // namespace passthrough
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h
new file mode 100644
index 0000000..33c914d
--- /dev/null
+++ b/graphics/composer/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/graphics/composer/2.1/utils/vts/Android.bp b/graphics/composer/2.1/utils/vts/Android.bp
new file mode 100644
index 0000000..846cfdf
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/Android.bp
@@ -0,0 +1,38 @@
+//
+// Copyright (C) 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.
+//
+
+cc_library_static {
+ name: "android.hardware.graphics.composer@2.1-vts",
+ defaults: ["hidl_defaults"],
+ srcs: [
+ "ComposerVts.cpp",
+ "GraphicsComposerCallback.cpp",
+ "TestCommandReader.cpp",
+ ],
+ static_libs: [
+ "VtsHalHidlTargetTestBase",
+ "android.hardware.graphics.composer@2.1",
+ ],
+ header_libs: [
+ "android.hardware.graphics.composer@2.1-command-buffer",
+ ],
+ cflags: [
+ "-O0",
+ "-g",
+ "-DLOG_TAG=\"ComposerVts\"",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.1/utils/vts/ComposerVts.cpp b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
new file mode 100644
index 0000000..2f531b4
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2017 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 <composer-vts/2.1/ComposerVts.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace vts {
+
+Composer::Composer() {
+ mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>();
+ init();
+}
+
+Composer::Composer(const std::string& name) {
+ mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>(name);
+ init();
+}
+
+void Composer::init() {
+ ASSERT_NE(nullptr, mComposer.get()) << "failed to get composer service";
+
+ std::vector<IComposer::Capability> capabilities = getCapabilities();
+ mCapabilities.insert(capabilities.begin(), capabilities.end());
+}
+
+sp<IComposer> Composer::getRaw() const {
+ return mComposer;
+}
+
+bool Composer::hasCapability(IComposer::Capability capability) const {
+ return mCapabilities.count(capability) > 0;
+}
+
+std::vector<IComposer::Capability> Composer::getCapabilities() {
+ std::vector<IComposer::Capability> capabilities;
+ mComposer->getCapabilities(
+ [&](const auto& tmpCapabilities) { capabilities = tmpCapabilities; });
+
+ return capabilities;
+}
+
+std::string Composer::dumpDebugInfo() {
+ std::string debugInfo;
+ mComposer->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
+
+ return debugInfo;
+}
+
+std::unique_ptr<ComposerClient> Composer::createClient() {
+ std::unique_ptr<ComposerClient> client;
+ mComposer->createClient([&](const auto& tmpError, const auto& tmpClient) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to create client";
+ client = std::make_unique<ComposerClient>(tmpClient);
+ });
+
+ return client;
+}
+
+ComposerClient::ComposerClient(const sp<IComposerClient>& client) : mClient(client) {}
+
+ComposerClient::~ComposerClient() {
+ for (auto it : mDisplayResources) {
+ Display display = it.first;
+ DisplayResource& resource = it.second;
+
+ for (auto layer : resource.layers) {
+ EXPECT_EQ(Error::NONE, mClient->destroyLayer(display, layer))
+ << "failed to destroy layer " << layer;
+ }
+
+ if (resource.isVirtual) {
+ EXPECT_EQ(Error::NONE, mClient->destroyVirtualDisplay(display))
+ << "failed to destroy virtual display " << display;
+ }
+ }
+ mDisplayResources.clear();
+}
+
+sp<IComposerClient> ComposerClient::getRaw() const {
+ return mClient;
+}
+
+void ComposerClient::registerCallback(const sp<IComposerCallback>& callback) {
+ mClient->registerCallback(callback);
+}
+
+uint32_t ComposerClient::getMaxVirtualDisplayCount() {
+ return mClient->getMaxVirtualDisplayCount();
+}
+
+Display ComposerClient::createVirtualDisplay(uint32_t width, uint32_t height,
+ PixelFormat formatHint, uint32_t outputBufferSlotCount,
+ PixelFormat* outFormat) {
+ Display display = 0;
+ mClient->createVirtualDisplay(
+ width, height, formatHint, outputBufferSlotCount,
+ [&](const auto& tmpError, const auto& tmpDisplay, const auto& tmpFormat) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to create virtual display";
+ display = tmpDisplay;
+ *outFormat = tmpFormat;
+
+ ASSERT_TRUE(mDisplayResources.insert({display, DisplayResource(true)}).second)
+ << "duplicated virtual display id " << display;
+ });
+
+ return display;
+}
+
+void ComposerClient::destroyVirtualDisplay(Display display) {
+ Error error = mClient->destroyVirtualDisplay(display);
+ ASSERT_EQ(Error::NONE, error) << "failed to destroy virtual display " << display;
+
+ mDisplayResources.erase(display);
+}
+
+Layer ComposerClient::createLayer(Display display, uint32_t bufferSlotCount) {
+ Layer layer = 0;
+ mClient->createLayer(display, bufferSlotCount, [&](const auto& tmpError, const auto& tmpLayer) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to create layer";
+ layer = tmpLayer;
+
+ auto resourceIt = mDisplayResources.find(display);
+ if (resourceIt == mDisplayResources.end()) {
+ resourceIt = mDisplayResources.insert({display, DisplayResource(false)}).first;
+ }
+
+ ASSERT_TRUE(resourceIt->second.layers.insert(layer).second)
+ << "duplicated layer id " << layer;
+ });
+
+ return layer;
+}
+
+void ComposerClient::destroyLayer(Display display, Layer layer) {
+ Error error = mClient->destroyLayer(display, layer);
+ ASSERT_EQ(Error::NONE, error) << "failed to destroy layer " << layer;
+
+ auto resourceIt = mDisplayResources.find(display);
+ ASSERT_NE(mDisplayResources.end(), resourceIt);
+ resourceIt->second.layers.erase(layer);
+}
+
+Config ComposerClient::getActiveConfig(Display display) {
+ Config config = 0;
+ mClient->getActiveConfig(display, [&](const auto& tmpError, const auto& tmpConfig) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to get active config";
+ config = tmpConfig;
+ });
+
+ return config;
+}
+
+bool ComposerClient::getClientTargetSupport(Display display, uint32_t width, uint32_t height,
+ PixelFormat format, Dataspace dataspace) {
+ Error error = mClient->getClientTargetSupport(display, width, height, format, dataspace);
+ return error == Error::NONE;
+}
+
+std::vector<ColorMode> ComposerClient::getColorModes(Display display) {
+ std::vector<ColorMode> modes;
+ mClient->getColorModes(display, [&](const auto& tmpError, const auto& tmpMode) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to get color mode";
+ modes = tmpMode;
+ });
+
+ return modes;
+}
+
+int32_t ComposerClient::getDisplayAttribute(Display display, Config config,
+ IComposerClient::Attribute attribute) {
+ int32_t value = 0;
+ mClient->getDisplayAttribute(
+ display, config, attribute, [&](const auto& tmpError, const auto& tmpValue) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to get display attribute";
+ value = tmpValue;
+ });
+
+ return value;
+}
+
+std::vector<Config> ComposerClient::getDisplayConfigs(Display display) {
+ std::vector<Config> configs;
+ mClient->getDisplayConfigs(display, [&](const auto& tmpError, const auto& tmpConfigs) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to get display configs";
+ configs = tmpConfigs;
+ });
+
+ return configs;
+}
+
+std::string ComposerClient::getDisplayName(Display display) {
+ std::string name;
+ mClient->getDisplayName(display, [&](const auto& tmpError, const auto& tmpName) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to get display name";
+ name = tmpName.c_str();
+ });
+
+ return name;
+}
+
+IComposerClient::DisplayType ComposerClient::getDisplayType(Display display) {
+ IComposerClient::DisplayType type = IComposerClient::DisplayType::INVALID;
+ mClient->getDisplayType(display, [&](const auto& tmpError, const auto& tmpType) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to get display type";
+ type = tmpType;
+ });
+
+ return type;
+}
+
+bool ComposerClient::getDozeSupport(Display display) {
+ bool support = false;
+ mClient->getDozeSupport(display, [&](const auto& tmpError, const auto& tmpSupport) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to get doze support";
+ support = tmpSupport;
+ });
+
+ return support;
+}
+
+std::vector<Hdr> ComposerClient::getHdrCapabilities(Display display, float* outMaxLuminance,
+ float* outMaxAverageLuminance,
+ float* outMinLuminance) {
+ std::vector<Hdr> types;
+ mClient->getHdrCapabilities(
+ display, [&](const auto& tmpError, const auto& tmpTypes, const auto& tmpMaxLuminance,
+ const auto& tmpMaxAverageLuminance, const auto& tmpMinLuminance) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to get HDR capabilities";
+ types = tmpTypes;
+ *outMaxLuminance = tmpMaxLuminance;
+ *outMaxAverageLuminance = tmpMaxAverageLuminance;
+ *outMinLuminance = tmpMinLuminance;
+ });
+
+ return types;
+}
+
+void ComposerClient::setClientTargetSlotCount(Display display, uint32_t clientTargetSlotCount) {
+ Error error = mClient->setClientTargetSlotCount(display, clientTargetSlotCount);
+ ASSERT_EQ(Error::NONE, error) << "failed to set client target slot count";
+}
+
+void ComposerClient::setActiveConfig(Display display, Config config) {
+ Error error = mClient->setActiveConfig(display, config);
+ ASSERT_EQ(Error::NONE, error) << "failed to set active config";
+}
+
+void ComposerClient::setColorMode(Display display, ColorMode mode) {
+ Error error = mClient->setColorMode(display, mode);
+ ASSERT_EQ(Error::NONE, error) << "failed to set color mode";
+}
+
+void ComposerClient::setPowerMode(Display display, IComposerClient::PowerMode mode) {
+ Error error = mClient->setPowerMode(display, mode);
+ ASSERT_EQ(Error::NONE, error) << "failed to set power mode";
+}
+
+void ComposerClient::setVsyncEnabled(Display display, bool enabled) {
+ IComposerClient::Vsync vsync =
+ (enabled) ? IComposerClient::Vsync::ENABLE : IComposerClient::Vsync::DISABLE;
+ Error error = mClient->setVsyncEnabled(display, vsync);
+ ASSERT_EQ(Error::NONE, error) << "failed to set vsync mode";
+
+ // give the hwbinder thread some time to handle any pending vsync callback
+ if (!enabled) {
+ usleep(5 * 1000);
+ }
+}
+
+void ComposerClient::execute(TestCommandReader* reader, CommandWriterBase* writer) {
+ bool queueChanged = false;
+ uint32_t commandLength = 0;
+ hidl_vec<hidl_handle> commandHandles;
+ ASSERT_TRUE(writer->writeQueue(&queueChanged, &commandLength, &commandHandles));
+
+ if (queueChanged) {
+ auto ret = mClient->setInputCommandQueue(*writer->getMQDescriptor());
+ ASSERT_EQ(Error::NONE, static_cast<Error>(ret));
+ return;
+ }
+
+ mClient->executeCommands(commandLength, commandHandles,
+ [&](const auto& tmpError, const auto& tmpOutQueueChanged,
+ const auto& tmpOutLength, const auto& tmpOutHandles) {
+ ASSERT_EQ(Error::NONE, tmpError);
+
+ if (tmpOutQueueChanged) {
+ mClient->getOutputCommandQueue(
+ [&](const auto& tmpError, const auto& tmpDescriptor) {
+ ASSERT_EQ(Error::NONE, tmpError);
+ reader->setMQDescriptor(tmpDescriptor);
+ });
+ }
+
+ ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles));
+ reader->parse();
+ });
+}
+
+} // namespace vts
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp b/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp
new file mode 100644
index 0000000..1ead138
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 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 <composer-vts/2.1/GraphicsComposerCallback.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace vts {
+
+void GraphicsComposerCallback::setVsyncAllowed(bool allowed) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mVsyncAllowed = allowed;
+}
+
+std::vector<Display> GraphicsComposerCallback::getDisplays() const {
+ std::lock_guard<std::mutex> lock(mMutex);
+ return std::vector<Display>(mDisplays.begin(), mDisplays.end());
+}
+
+int GraphicsComposerCallback::getInvalidHotplugCount() const {
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mInvalidHotplugCount;
+}
+
+int GraphicsComposerCallback::getInvalidRefreshCount() const {
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mInvalidRefreshCount;
+}
+
+int GraphicsComposerCallback::getInvalidVsyncCount() const {
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mInvalidVsyncCount;
+}
+
+Return<void> GraphicsComposerCallback::onHotplug(Display display, Connection connection) {
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ if (connection == Connection::CONNECTED) {
+ if (!mDisplays.insert(display).second) {
+ mInvalidHotplugCount++;
+ }
+ } else if (connection == Connection::DISCONNECTED) {
+ if (!mDisplays.erase(display)) {
+ mInvalidHotplugCount++;
+ }
+ }
+
+ return Void();
+}
+
+Return<void> GraphicsComposerCallback::onRefresh(Display display) {
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ if (mDisplays.count(display) == 0) {
+ mInvalidRefreshCount++;
+ }
+
+ return Void();
+}
+
+Return<void> GraphicsComposerCallback::onVsync(Display display, int64_t) {
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ if (!mVsyncAllowed || mDisplays.count(display) == 0) {
+ mInvalidVsyncCount++;
+ }
+
+ return Void();
+}
+
+} // namespace vts
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.1/utils/vts/TestCommandReader.cpp b/graphics/composer/2.1/utils/vts/TestCommandReader.cpp
new file mode 100644
index 0000000..6f8f1ad
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/TestCommandReader.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 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 <composer-vts/2.1/TestCommandReader.h>
+
+#include <gtest/gtest.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace vts {
+
+void TestCommandReader::parse() {
+ while (!isEmpty()) {
+ IComposerClient::Command command;
+ uint16_t length;
+ ASSERT_TRUE(beginCommand(&command, &length));
+
+ switch (command) {
+ case IComposerClient::Command::SET_ERROR: {
+ ASSERT_EQ(2, length);
+ auto loc = read();
+ auto err = readSigned();
+ GTEST_FAIL() << "unexpected error " << err << " at location " << loc;
+ } break;
+ case IComposerClient::Command::SELECT_DISPLAY:
+ case IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES:
+ case IComposerClient::Command::SET_DISPLAY_REQUESTS:
+ case IComposerClient::Command::SET_PRESENT_FENCE:
+ case IComposerClient::Command::SET_RELEASE_FENCES:
+ break;
+ default:
+ GTEST_FAIL() << "unexpected return command " << std::hex
+ << static_cast<int>(command);
+ break;
+ }
+
+ endCommand();
+ }
+}
+
+} // namespace vts
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
new file mode 100644
index 0000000..0d883e4
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2017 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 <memory>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
+#include <composer-vts/2.1/TestCommandReader.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace vts {
+
+using android::hardware::graphics::common::V1_0::ColorMode;
+using android::hardware::graphics::common::V1_0::Dataspace;
+using android::hardware::graphics::common::V1_0::Hdr;
+using android::hardware::graphics::common::V1_0::PixelFormat;
+
+class ComposerClient;
+
+// A wrapper to IComposer.
+class Composer {
+ public:
+ Composer();
+ explicit Composer(const std::string& name);
+
+ sp<IComposer> getRaw() const;
+
+ // Returns true when the composer supports the specified capability.
+ bool hasCapability(IComposer::Capability capability) const;
+
+ std::vector<IComposer::Capability> getCapabilities();
+ std::string dumpDebugInfo();
+ std::unique_ptr<ComposerClient> createClient();
+
+ protected:
+ sp<IComposer> mComposer;
+
+ private:
+ void init();
+
+ std::unordered_set<IComposer::Capability> mCapabilities;
+};
+
+// A wrapper to IComposerClient.
+class ComposerClient {
+ public:
+ ComposerClient(const sp<IComposerClient>& client);
+ ~ComposerClient();
+
+ sp<IComposerClient> getRaw() const;
+
+ void registerCallback(const sp<IComposerCallback>& callback);
+ uint32_t getMaxVirtualDisplayCount();
+
+ Display createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat formatHint,
+ uint32_t outputBufferSlotCount, PixelFormat* outFormat);
+ void destroyVirtualDisplay(Display display);
+
+ Layer createLayer(Display display, uint32_t bufferSlotCount);
+ void destroyLayer(Display display, Layer layer);
+
+ Config getActiveConfig(Display display);
+ bool getClientTargetSupport(Display display, uint32_t width, uint32_t height,
+ PixelFormat format, Dataspace dataspace);
+ std::vector<ColorMode> getColorModes(Display display);
+ int32_t getDisplayAttribute(Display display, Config config,
+ IComposerClient::Attribute attribute);
+ std::vector<Config> getDisplayConfigs(Display display);
+ std::string getDisplayName(Display display);
+ IComposerClient::DisplayType getDisplayType(Display display);
+ bool getDozeSupport(Display display);
+ std::vector<Hdr> getHdrCapabilities(Display display, float* outMaxLuminance,
+ float* outMaxAverageLuminance, float* outMinLuminance);
+
+ void setClientTargetSlotCount(Display display, uint32_t clientTargetSlotCount);
+ void setActiveConfig(Display display, Config config);
+ void setColorMode(Display display, ColorMode mode);
+ void setPowerMode(Display display, IComposerClient::PowerMode mode);
+ void setVsyncEnabled(Display display, bool enabled);
+
+ void execute(TestCommandReader* reader, CommandWriterBase* writer);
+
+ private:
+ sp<IComposerClient> mClient;
+
+ // Keep track of all virtual displays and layers. When a test fails with
+ // ASSERT_*, the destructor will clean up the resources for the test.
+ struct DisplayResource {
+ DisplayResource(bool isVirtual_) : isVirtual(isVirtual_) {}
+
+ bool isVirtual;
+ std::unordered_set<Layer> layers;
+ };
+ std::unordered_map<Display, DisplayResource> mDisplayResources;
+};
+
+} // namespace vts
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h
new file mode 100644
index 0000000..e3c348f
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2017 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 <android/hardware/graphics/composer/2.1/IComposerCallback.h>
+
+#include <mutex>
+#include <unordered_set>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace vts {
+
+// IComposerCallback to be installed with IComposerClient::registerCallback.
+class GraphicsComposerCallback : public IComposerCallback {
+ public:
+ void setVsyncAllowed(bool allowed);
+
+ std::vector<Display> getDisplays() const;
+
+ int getInvalidHotplugCount() const;
+
+ int getInvalidRefreshCount() const;
+
+ int getInvalidVsyncCount() const;
+
+ private:
+ Return<void> onHotplug(Display display, Connection connection) override;
+ Return<void> onRefresh(Display display) override;
+ Return<void> onVsync(Display display, int64_t) override;
+
+ mutable std::mutex mMutex;
+ // the set of all currently connected displays
+ std::unordered_set<Display> mDisplays;
+ // true only when vsync is enabled
+ bool mVsyncAllowed = true;
+
+ // track invalid callbacks
+ int mInvalidHotplugCount = 0;
+ int mInvalidRefreshCount = 0;
+ int mInvalidVsyncCount = 0;
+};
+
+} // namespace vts
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.1/vts/functional/TestCommandReader.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h
similarity index 79%
rename from graphics/composer/2.1/vts/functional/TestCommandReader.h
rename to graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h
index ae25d2d..3888eeb 100644
--- a/graphics/composer/2.1/vts/functional/TestCommandReader.h
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef TEST_COMMAND_READER_H
-#define TEST_COMMAND_READER_H
+#pragma once
#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
@@ -24,22 +23,20 @@
namespace graphics {
namespace composer {
namespace V2_1 {
-namespace tests {
+namespace vts {
// A command parser that checks that no error nor unexpected commands are
// returned.
class TestCommandReader : public CommandReaderBase {
- public:
- // Parse all commands in the return command queue. Call GTEST_FAIL() for
- // unexpected errors or commands.
- void parse();
+ public:
+ // Parse all commands in the return command queue. Call GTEST_FAIL() for
+ // unexpected errors or commands.
+ void parse();
};
-} // namespace tests
+} // namespace vts
} // namespace V2_1
} // namespace composer
} // namespace graphics
} // namespace hardware
} // namespace android
-
-#endif // TEST_COMMAND_READER_H
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index 92b65a3..8e346df 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -14,36 +14,6 @@
// limitations under the License.
//
-cc_library_static {
- name: "libVtsHalGraphicsComposerTestUtils",
- defaults: ["hidl_defaults"],
- srcs: [
- "GraphicsComposerCallback.cpp",
- "TestCommandReader.cpp",
- "VtsHalGraphicsComposerTestUtils.cpp",
- ],
- shared_libs: [
- "android.hardware.graphics.composer@2.1",
- "libfmq",
- "libsync",
- ],
- static_libs: [
- "VtsHalHidlTargetTestBase",
- ],
- header_libs: [
- "android.hardware.graphics.composer@2.1-command-buffer",
- ],
- cflags: [
- "-Wall",
- "-Wextra",
- "-Werror",
- "-O0",
- "-g",
- "-DLOG_TAG=\"GraphicsComposerTestUtils\"",
- ],
- export_include_dirs: ["."],
-}
-
cc_test {
name: "VtsHalGraphicsComposerV2_1TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
@@ -57,10 +27,9 @@
static_libs: [
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.1-vts",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.0-vts",
- "libVtsHalGraphicsComposerTestUtils",
- "libnativehelper",
],
header_libs: [
"android.hardware.graphics.composer@2.1-command-buffer",
diff --git a/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.cpp b/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.cpp
deleted file mode 100644
index 0ad440c..0000000
--- a/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2017 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 "GraphicsComposerCallback.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace tests {
-
-void GraphicsComposerCallback::setVsyncAllowed(bool allowed) {
- std::lock_guard<std::mutex> lock(mMutex);
- mVsyncAllowed = allowed;
-}
-
-std::vector<Display> GraphicsComposerCallback::getDisplays() const {
- std::lock_guard<std::mutex> lock(mMutex);
- return std::vector<Display>(mDisplays.begin(), mDisplays.end());
-}
-
-int GraphicsComposerCallback::getInvalidHotplugCount() const {
- std::lock_guard<std::mutex> lock(mMutex);
- return mInvalidHotplugCount;
-}
-
-int GraphicsComposerCallback::getInvalidRefreshCount() const {
- std::lock_guard<std::mutex> lock(mMutex);
- return mInvalidRefreshCount;
-}
-
-int GraphicsComposerCallback::getInvalidVsyncCount() const {
- std::lock_guard<std::mutex> lock(mMutex);
- return mInvalidVsyncCount;
-}
-
-Return<void> GraphicsComposerCallback::onHotplug(Display display,
- Connection connection) {
- std::lock_guard<std::mutex> lock(mMutex);
-
- if (connection == Connection::CONNECTED) {
- if (!mDisplays.insert(display).second) {
- mInvalidHotplugCount++;
- }
- } else if (connection == Connection::DISCONNECTED) {
- if (!mDisplays.erase(display)) {
- mInvalidHotplugCount++;
- }
- }
-
- return Void();
-}
-
-Return<void> GraphicsComposerCallback::onRefresh(Display display) {
- std::lock_guard<std::mutex> lock(mMutex);
-
- if (mDisplays.count(display) == 0) {
- mInvalidRefreshCount++;
- }
-
- return Void();
-}
-
-Return<void> GraphicsComposerCallback::onVsync(Display display, int64_t) {
- std::lock_guard<std::mutex> lock(mMutex);
-
- if (!mVsyncAllowed || mDisplays.count(display) == 0) {
- mInvalidVsyncCount++;
- }
-
- return Void();
-}
-
-} // namespace tests
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.h b/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.h
deleted file mode 100644
index e332086..0000000
--- a/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef GRAPHICS_COMPOSER_CALLBACK_H
-#define GRAPHICS_COMPOSER_CALLBACK_H
-
-#include <android/hardware/graphics/composer/2.1/IComposerCallback.h>
-
-#include <mutex>
-#include <unordered_set>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace tests {
-
-// IComposerCallback to be installed with IComposerClient::registerCallback.
-class GraphicsComposerCallback : public IComposerCallback {
- public:
- void setVsyncAllowed(bool allowed);
-
- std::vector<Display> getDisplays() const;
-
- int getInvalidHotplugCount() const;
-
- int getInvalidRefreshCount() const;
-
- int getInvalidVsyncCount() const;
-
- private:
- Return<void> onHotplug(Display display, Connection connection) override;
- Return<void> onRefresh(Display display) override;
- Return<void> onVsync(Display display, int64_t) override;
-
- mutable std::mutex mMutex;
- // the set of all currently connected displays
- std::unordered_set<Display> mDisplays;
- // true only when vsync is enabled
- bool mVsyncAllowed = true;
-
- // track invalid callbacks
- int mInvalidHotplugCount = 0;
- int mInvalidRefreshCount = 0;
- int mInvalidVsyncCount = 0;
-};
-
-} // namespace tests
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
-
-#endif // GRAPHICS_COMPOSER_CALLBACK_H
diff --git a/graphics/composer/2.1/vts/functional/TestCommandReader.cpp b/graphics/composer/2.1/vts/functional/TestCommandReader.cpp
deleted file mode 100644
index b1f9aca..0000000
--- a/graphics/composer/2.1/vts/functional/TestCommandReader.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2017 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 "TestCommandReader.h"
-
-#include <gtest/gtest.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace tests {
-
-void TestCommandReader::parse() {
- while (!isEmpty()) {
- IComposerClient::Command command;
- uint16_t length;
- ASSERT_TRUE(beginCommand(&command, &length));
-
- switch (command) {
- case IComposerClient::Command::SET_ERROR: {
- ASSERT_EQ(2, length);
- auto loc = read();
- auto err = readSigned();
- GTEST_FAIL() << "unexpected error " << err << " at location " << loc;
- } break;
- case IComposerClient::Command::SELECT_DISPLAY:
- case IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES:
- case IComposerClient::Command::SET_DISPLAY_REQUESTS:
- case IComposerClient::Command::SET_PRESENT_FENCE:
- case IComposerClient::Command::SET_RELEASE_FENCES:
- break;
- default:
- GTEST_FAIL() << "unexpected return command " << std::hex
- << static_cast<int>(command);
- break;
- }
-
- endCommand();
- }
-}
-
-} // namespace tests
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.cpp
deleted file mode 100644
index c66cdd0..0000000
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.cpp
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * Copyright (C) 2017 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 <VtsHalHidlTargetTestBase.h>
-
-#include "VtsHalGraphicsComposerTestUtils.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace tests {
-
-Composer::Composer() {
- mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>();
- init();
-}
-
-Composer::Composer(const std::string& name) {
- mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>(name);
- init();
-}
-
-void Composer::init() {
- ASSERT_NE(nullptr, mComposer.get()) << "failed to get composer service";
-
- std::vector<IComposer::Capability> capabilities = getCapabilities();
- mCapabilities.insert(capabilities.begin(), capabilities.end());
-}
-
-sp<IComposer> Composer::getRaw() const { return mComposer; }
-
-bool Composer::hasCapability(IComposer::Capability capability) const {
- return mCapabilities.count(capability) > 0;
-}
-
-std::vector<IComposer::Capability> Composer::getCapabilities() {
- std::vector<IComposer::Capability> capabilities;
- mComposer->getCapabilities(
- [&](const auto& tmpCapabilities) { capabilities = tmpCapabilities; });
-
- return capabilities;
-}
-
-std::string Composer::dumpDebugInfo() {
- std::string debugInfo;
- mComposer->dumpDebugInfo(
- [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
-
- return debugInfo;
-}
-
-std::unique_ptr<ComposerClient> Composer::createClient() {
- std::unique_ptr<ComposerClient> client;
- mComposer->createClient([&](const auto& tmpError, const auto& tmpClient) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to create client";
- client = std::make_unique<ComposerClient>(tmpClient);
- });
-
- return client;
-}
-
-ComposerClient::ComposerClient(const sp<IComposerClient>& client)
- : mClient(client) {}
-
-ComposerClient::~ComposerClient() {
- for (auto it : mDisplayResources) {
- Display display = it.first;
- DisplayResource& resource = it.second;
-
- for (auto layer : resource.layers) {
- EXPECT_EQ(Error::NONE, mClient->destroyLayer(display, layer))
- << "failed to destroy layer " << layer;
- }
-
- if (resource.isVirtual) {
- EXPECT_EQ(Error::NONE, mClient->destroyVirtualDisplay(display))
- << "failed to destroy virtual display " << display;
- }
- }
- mDisplayResources.clear();
-}
-
-sp<IComposerClient> ComposerClient::getRaw() const { return mClient; }
-
-void ComposerClient::registerCallback(const sp<IComposerCallback>& callback) {
- mClient->registerCallback(callback);
-}
-
-uint32_t ComposerClient::getMaxVirtualDisplayCount() {
- return mClient->getMaxVirtualDisplayCount();
-}
-
-Display ComposerClient::createVirtualDisplay(uint32_t width, uint32_t height,
- PixelFormat formatHint,
- uint32_t outputBufferSlotCount,
- PixelFormat* outFormat) {
- Display display = 0;
- mClient->createVirtualDisplay(
- width, height, formatHint, outputBufferSlotCount,
- [&](const auto& tmpError, const auto& tmpDisplay, const auto& tmpFormat) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to create virtual display";
- display = tmpDisplay;
- *outFormat = tmpFormat;
-
- ASSERT_TRUE(
- mDisplayResources.insert({display, DisplayResource(true)}).second)
- << "duplicated virtual display id " << display;
- });
-
- return display;
-}
-
-void ComposerClient::destroyVirtualDisplay(Display display) {
- Error error = mClient->destroyVirtualDisplay(display);
- ASSERT_EQ(Error::NONE, error)
- << "failed to destroy virtual display " << display;
-
- mDisplayResources.erase(display);
-}
-
-Layer ComposerClient::createLayer(Display display, uint32_t bufferSlotCount) {
- Layer layer = 0;
- mClient->createLayer(
- display, bufferSlotCount,
- [&](const auto& tmpError, const auto& tmpLayer) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to create layer";
- layer = tmpLayer;
-
- auto resourceIt = mDisplayResources.find(display);
- if (resourceIt == mDisplayResources.end()) {
- resourceIt =
- mDisplayResources.insert({display, DisplayResource(false)}).first;
- }
-
- ASSERT_TRUE(resourceIt->second.layers.insert(layer).second)
- << "duplicated layer id " << layer;
- });
-
- return layer;
-}
-
-void ComposerClient::destroyLayer(Display display, Layer layer) {
- Error error = mClient->destroyLayer(display, layer);
- ASSERT_EQ(Error::NONE, error) << "failed to destroy layer " << layer;
-
- auto resourceIt = mDisplayResources.find(display);
- ASSERT_NE(mDisplayResources.end(), resourceIt);
- resourceIt->second.layers.erase(layer);
-}
-
-Config ComposerClient::getActiveConfig(Display display) {
- Config config = 0;
- mClient->getActiveConfig(
- display, [&](const auto& tmpError, const auto& tmpConfig) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to get active config";
- config = tmpConfig;
- });
-
- return config;
-}
-
-bool ComposerClient::getClientTargetSupport(Display display, uint32_t width,
- uint32_t height, PixelFormat format,
- Dataspace dataspace) {
- Error error = mClient->getClientTargetSupport(display, width, height, format,
- dataspace);
- return error == Error::NONE;
-}
-
-std::vector<ColorMode> ComposerClient::getColorModes(Display display) {
- std::vector<ColorMode> modes;
- mClient->getColorModes(
- display, [&](const auto& tmpError, const auto& tmpMode) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to get color mode";
- modes = tmpMode;
- });
-
- return modes;
-}
-
-int32_t ComposerClient::getDisplayAttribute(
- Display display, Config config, IComposerClient::Attribute attribute) {
- int32_t value = 0;
- mClient->getDisplayAttribute(display, config, attribute,
- [&](const auto& tmpError, const auto& tmpValue) {
- ASSERT_EQ(Error::NONE, tmpError)
- << "failed to get display attribute";
- value = tmpValue;
- });
-
- return value;
-}
-
-std::vector<Config> ComposerClient::getDisplayConfigs(Display display) {
- std::vector<Config> configs;
- mClient->getDisplayConfigs(
- display, [&](const auto& tmpError, const auto& tmpConfigs) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to get display configs";
- configs = tmpConfigs;
- });
-
- return configs;
-}
-
-std::string ComposerClient::getDisplayName(Display display) {
- std::string name;
- mClient->getDisplayName(
- display, [&](const auto& tmpError, const auto& tmpName) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to get display name";
- name = tmpName.c_str();
- });
-
- return name;
-}
-
-IComposerClient::DisplayType ComposerClient::getDisplayType(Display display) {
- IComposerClient::DisplayType type = IComposerClient::DisplayType::INVALID;
- mClient->getDisplayType(
- display, [&](const auto& tmpError, const auto& tmpType) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to get display type";
- type = tmpType;
- });
-
- return type;
-}
-
-bool ComposerClient::getDozeSupport(Display display) {
- bool support = false;
- mClient->getDozeSupport(
- display, [&](const auto& tmpError, const auto& tmpSupport) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to get doze support";
- support = tmpSupport;
- });
-
- return support;
-}
-
-std::vector<Hdr> ComposerClient::getHdrCapabilities(
- Display display, float* outMaxLuminance, float* outMaxAverageLuminance,
- float* outMinLuminance) {
- std::vector<Hdr> types;
- mClient->getHdrCapabilities(
- display,
- [&](const auto& tmpError, const auto& tmpTypes,
- const auto& tmpMaxLuminance, const auto& tmpMaxAverageLuminance,
- const auto& tmpMinLuminance) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to get HDR capabilities";
- types = tmpTypes;
- *outMaxLuminance = tmpMaxLuminance;
- *outMaxAverageLuminance = tmpMaxAverageLuminance;
- *outMinLuminance = tmpMinLuminance;
- });
-
- return types;
-}
-
-void ComposerClient::setClientTargetSlotCount(Display display,
- uint32_t clientTargetSlotCount) {
- Error error =
- mClient->setClientTargetSlotCount(display, clientTargetSlotCount);
- ASSERT_EQ(Error::NONE, error) << "failed to set client target slot count";
-}
-
-void ComposerClient::setActiveConfig(Display display, Config config) {
- Error error = mClient->setActiveConfig(display, config);
- ASSERT_EQ(Error::NONE, error) << "failed to set active config";
-}
-
-void ComposerClient::setColorMode(Display display, ColorMode mode) {
- Error error = mClient->setColorMode(display, mode);
- ASSERT_EQ(Error::NONE, error) << "failed to set color mode";
-}
-
-void ComposerClient::setPowerMode(Display display,
- IComposerClient::PowerMode mode) {
- Error error = mClient->setPowerMode(display, mode);
- ASSERT_EQ(Error::NONE, error) << "failed to set power mode";
-}
-
-void ComposerClient::setVsyncEnabled(Display display, bool enabled) {
- IComposerClient::Vsync vsync = (enabled) ? IComposerClient::Vsync::ENABLE
- : IComposerClient::Vsync::DISABLE;
- Error error = mClient->setVsyncEnabled(display, vsync);
- ASSERT_EQ(Error::NONE, error) << "failed to set vsync mode";
-
- // give the hwbinder thread some time to handle any pending vsync callback
- if (!enabled) {
- usleep(5 * 1000);
- }
-}
-
-void ComposerClient::execute(TestCommandReader* reader,
- CommandWriterBase* writer) {
- bool queueChanged = false;
- uint32_t commandLength = 0;
- hidl_vec<hidl_handle> commandHandles;
- ASSERT_TRUE(
- writer->writeQueue(&queueChanged, &commandLength, &commandHandles));
-
- if (queueChanged) {
- auto ret = mClient->setInputCommandQueue(*writer->getMQDescriptor());
- ASSERT_EQ(Error::NONE, static_cast<Error>(ret));
- return;
- }
-
- mClient->executeCommands(
- commandLength, commandHandles,
- [&](const auto& tmpError, const auto& tmpOutQueueChanged,
- const auto& tmpOutLength, const auto& tmpOutHandles) {
- ASSERT_EQ(Error::NONE, tmpError);
-
- if (tmpOutQueueChanged) {
- mClient->getOutputCommandQueue(
- [&](const auto& tmpError, const auto& tmpDescriptor) {
- ASSERT_EQ(Error::NONE, tmpError);
- reader->setMQDescriptor(tmpDescriptor);
- });
- }
-
- ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles));
- reader->parse();
- });
-}
-
-} // namespace tests
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.h b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.h
deleted file mode 100644
index 00d9d8c..0000000
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef VTS_HAL_GRAPHICS_COMPOSER_UTILS
-#define VTS_HAL_GRAPHICS_COMPOSER_UTILS
-
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
-
-#include <android/hardware/graphics/composer/2.1/IComposer.h>
-#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
-#include <utils/StrongPointer.h>
-
-#include "TestCommandReader.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace tests {
-
-using android::hardware::graphics::common::V1_0::ColorMode;
-using android::hardware::graphics::common::V1_0::Dataspace;
-using android::hardware::graphics::common::V1_0::Hdr;
-using android::hardware::graphics::common::V1_0::PixelFormat;
-
-class ComposerClient;
-
-// A wrapper to IComposer.
-class Composer {
- public:
- Composer();
- explicit Composer(const std::string& name);
-
- sp<IComposer> getRaw() const;
-
- // Returns true when the composer supports the specified capability.
- bool hasCapability(IComposer::Capability capability) const;
-
- std::vector<IComposer::Capability> getCapabilities();
- std::string dumpDebugInfo();
- std::unique_ptr<ComposerClient> createClient();
-
- protected:
- sp<IComposer> mComposer;
-
- private:
- void init();
-
- std::unordered_set<IComposer::Capability> mCapabilities;
-};
-
-// A wrapper to IComposerClient.
-class ComposerClient {
- public:
- ComposerClient(const sp<IComposerClient>& client);
- ~ComposerClient();
-
- sp<IComposerClient> getRaw() const;
-
- void registerCallback(const sp<IComposerCallback>& callback);
- uint32_t getMaxVirtualDisplayCount();
-
- Display createVirtualDisplay(uint32_t width, uint32_t height,
- PixelFormat formatHint,
- uint32_t outputBufferSlotCount,
- PixelFormat* outFormat);
- void destroyVirtualDisplay(Display display);
-
- Layer createLayer(Display display, uint32_t bufferSlotCount);
- void destroyLayer(Display display, Layer layer);
-
- Config getActiveConfig(Display display);
- bool getClientTargetSupport(Display display, uint32_t width, uint32_t height,
- PixelFormat format, Dataspace dataspace);
- std::vector<ColorMode> getColorModes(Display display);
- int32_t getDisplayAttribute(Display display, Config config,
- IComposerClient::Attribute attribute);
- std::vector<Config> getDisplayConfigs(Display display);
- std::string getDisplayName(Display display);
- IComposerClient::DisplayType getDisplayType(Display display);
- bool getDozeSupport(Display display);
- std::vector<Hdr> getHdrCapabilities(Display display, float* outMaxLuminance,
- float* outMaxAverageLuminance,
- float* outMinLuminance);
-
- void setClientTargetSlotCount(Display display,
- uint32_t clientTargetSlotCount);
- void setActiveConfig(Display display, Config config);
- void setColorMode(Display display, ColorMode mode);
- void setPowerMode(Display display, IComposerClient::PowerMode mode);
- void setVsyncEnabled(Display display, bool enabled);
-
- void execute(TestCommandReader* reader, CommandWriterBase* writer);
-
- private:
- sp<IComposerClient> mClient;
-
- // Keep track of all virtual displays and layers. When a test fails with
- // ASSERT_*, the destructor will clean up the resources for the test.
- struct DisplayResource {
- DisplayResource(bool isVirtual_) : isVirtual(isVirtual_) {}
-
- bool isVirtual;
- std::unordered_set<Layer> layers;
- };
- std::unordered_map<Display, DisplayResource> mDisplayResources;
-};
-
-} // namespace tests
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
-
-#endif // VTS_HAL_GRAPHICS_COMPOSER_UTILS
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 376ee37..8b8b530 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -17,10 +17,10 @@
#define LOG_TAG "graphics_composer_hidl_hal_test"
#include <android-base/logging.h>
+#include <composer-vts/2.1/ComposerVts.h>
+#include <composer-vts/2.1/GraphicsComposerCallback.h>
+#include <composer-vts/2.1/TestCommandReader.h>
#include <mapper-vts/2.0/MapperVts.h>
-#include "GraphicsComposerCallback.h"
-#include "TestCommandReader.h"
-#include "VtsHalGraphicsComposerTestUtils.h"
#include <VtsHalHidlTargetTestBase.h>
#include <VtsHalHidlTargetTestEnvBase.h>
@@ -38,7 +38,7 @@
namespace graphics {
namespace composer {
namespace V2_1 {
-namespace tests {
+namespace vts {
namespace {
using android::hardware::graphics::common::V1_0::BufferUsage;
@@ -69,53 +69,53 @@
};
class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- protected:
- void SetUp() override {
- ASSERT_NO_FATAL_FAILURE(
- mComposer = std::make_unique<Composer>(
- GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
- ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
+ protected:
+ void SetUp() override {
+ ASSERT_NO_FATAL_FAILURE(
+ mComposer = std::make_unique<Composer>(
+ GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
+ ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
- mComposerCallback = new GraphicsComposerCallback;
- mComposerClient->registerCallback(mComposerCallback);
+ mComposerCallback = new GraphicsComposerCallback;
+ mComposerClient->registerCallback(mComposerCallback);
- // assume the first display is primary and is never removed
- mPrimaryDisplay = waitForFirstDisplay();
+ // assume the first display is primary and is never removed
+ mPrimaryDisplay = waitForFirstDisplay();
- // explicitly disable vsync
- mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
- mComposerCallback->setVsyncAllowed(false);
- }
-
- void TearDown() override {
- if (mComposerCallback != nullptr) {
- EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
- EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
- EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
+ // explicitly disable vsync
+ mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
+ mComposerCallback->setVsyncAllowed(false);
}
- }
- // use the slot count usually set by SF
- static constexpr uint32_t kBufferSlotCount = 64;
-
- std::unique_ptr<Composer> mComposer;
- std::unique_ptr<ComposerClient> mComposerClient;
- sp<GraphicsComposerCallback> mComposerCallback;
- // the first display and is assumed never to be removed
- Display mPrimaryDisplay;
-
- private:
- Display waitForFirstDisplay() {
- while (true) {
- std::vector<Display> displays = mComposerCallback->getDisplays();
- if (displays.empty()) {
- usleep(5 * 1000);
- continue;
- }
-
- return displays[0];
+ void TearDown() override {
+ if (mComposerCallback != nullptr) {
+ EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
+ EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
+ EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
+ }
}
- }
+
+ // use the slot count usually set by SF
+ static constexpr uint32_t kBufferSlotCount = 64;
+
+ std::unique_ptr<Composer> mComposer;
+ std::unique_ptr<ComposerClient> mComposerClient;
+ sp<GraphicsComposerCallback> mComposerCallback;
+ // the first display and is assumed never to be removed
+ Display mPrimaryDisplay;
+
+ private:
+ Display waitForFirstDisplay() {
+ while (true) {
+ std::vector<Display> displays = mComposerCallback->getDisplays();
+ if (displays.empty()) {
+ usleep(5 * 1000);
+ continue;
+ }
+
+ return displays[0];
+ }
+ }
};
/**
@@ -124,16 +124,17 @@
* Test that IComposer::getCapabilities returns no invalid capabilities.
*/
TEST_F(GraphicsComposerHidlTest, GetCapabilities) {
- auto capabilities = mComposer->getCapabilities();
- ASSERT_EQ(capabilities.end(),
- std::find(capabilities.begin(), capabilities.end(),
- IComposer::Capability::INVALID));
+ auto capabilities = mComposer->getCapabilities();
+ ASSERT_EQ(capabilities.end(),
+ std::find(capabilities.begin(), capabilities.end(), IComposer::Capability::INVALID));
}
/**
* Test IComposer::dumpDebugInfo.
*/
-TEST_F(GraphicsComposerHidlTest, DumpDebugInfo) { mComposer->dumpDebugInfo(); }
+TEST_F(GraphicsComposerHidlTest, DumpDebugInfo) {
+ mComposer->dumpDebugInfo();
+}
/**
* Test IComposer::createClient.
@@ -141,9 +142,8 @@
* Test that IComposerClient is a singleton.
*/
TEST_F(GraphicsComposerHidlTest, CreateClientSingleton) {
- mComposer->getRaw()->createClient([&](const auto& tmpError, const auto&) {
- EXPECT_EQ(Error::NO_RESOURCES, tmpError);
- });
+ mComposer->getRaw()->createClient(
+ [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::NO_RESOURCES, tmpError); });
}
/**
@@ -153,22 +153,22 @@
* Test that virtual displays can be created and has the correct display type.
*/
TEST_F(GraphicsComposerHidlTest, CreateVirtualDisplay) {
- if (mComposerClient->getMaxVirtualDisplayCount() == 0) {
- GTEST_SUCCEED() << "no virtual display support";
- return;
- }
+ if (mComposerClient->getMaxVirtualDisplayCount() == 0) {
+ GTEST_SUCCEED() << "no virtual display support";
+ return;
+ }
- Display display;
- PixelFormat format;
- ASSERT_NO_FATAL_FAILURE(display = mComposerClient->createVirtualDisplay(
- 64, 64, PixelFormat::IMPLEMENTATION_DEFINED,
- kBufferSlotCount, &format));
+ Display display;
+ PixelFormat format;
+ ASSERT_NO_FATAL_FAILURE(
+ display = mComposerClient->createVirtualDisplay(64, 64, PixelFormat::IMPLEMENTATION_DEFINED,
+ kBufferSlotCount, &format));
- // test display type
- IComposerClient::DisplayType type = mComposerClient->getDisplayType(display);
- EXPECT_EQ(IComposerClient::DisplayType::VIRTUAL, type);
+ // test display type
+ IComposerClient::DisplayType type = mComposerClient->getDisplayType(display);
+ EXPECT_EQ(IComposerClient::DisplayType::VIRTUAL, type);
- mComposerClient->destroyVirtualDisplay(display);
+ mComposerClient->destroyVirtualDisplay(display);
}
/**
@@ -177,18 +177,18 @@
* Test that layers can be created and destroyed.
*/
TEST_F(GraphicsComposerHidlTest, CreateLayer) {
- Layer layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+ Layer layer;
+ ASSERT_NO_FATAL_FAILURE(layer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
- mComposerClient->destroyLayer(mPrimaryDisplay, layer);
+ mComposerClient->destroyLayer(mPrimaryDisplay, layer);
}
/**
* Test IComposerClient::getDisplayName.
*/
TEST_F(GraphicsComposerHidlTest, GetDisplayName) {
- mComposerClient->getDisplayName(mPrimaryDisplay);
+ mComposerClient->getDisplayName(mPrimaryDisplay);
}
/**
@@ -198,8 +198,8 @@
* for the primary display.
*/
TEST_F(GraphicsComposerHidlTest, GetDisplayType) {
- ASSERT_EQ(IComposerClient::DisplayType::PHYSICAL,
- mComposerClient->getDisplayType(mPrimaryDisplay));
+ ASSERT_EQ(IComposerClient::DisplayType::PHYSICAL,
+ mComposerClient->getDisplayType(mPrimaryDisplay));
}
/**
@@ -209,22 +209,20 @@
* required client targets.
*/
TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport) {
- std::vector<Config> configs =
- mComposerClient->getDisplayConfigs(mPrimaryDisplay);
- for (auto config : configs) {
- int32_t width = mComposerClient->getDisplayAttribute(
- mPrimaryDisplay, config, IComposerClient::Attribute::WIDTH);
- int32_t height = mComposerClient->getDisplayAttribute(
- mPrimaryDisplay, config, IComposerClient::Attribute::HEIGHT);
- ASSERT_LT(0, width);
- ASSERT_LT(0, height);
+ std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
+ for (auto config : configs) {
+ int32_t width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+ IComposerClient::Attribute::WIDTH);
+ int32_t height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+ IComposerClient::Attribute::HEIGHT);
+ ASSERT_LT(0, width);
+ ASSERT_LT(0, height);
- mComposerClient->setActiveConfig(mPrimaryDisplay, config);
+ mComposerClient->setActiveConfig(mPrimaryDisplay, config);
- ASSERT_TRUE(mComposerClient->getClientTargetSupport(
- mPrimaryDisplay, width, height, PixelFormat::RGBA_8888,
- Dataspace::UNKNOWN));
- }
+ ASSERT_TRUE(mComposerClient->getClientTargetSupport(
+ mPrimaryDisplay, width, height, PixelFormat::RGBA_8888, Dataspace::UNKNOWN));
+ }
}
/**
@@ -234,47 +232,44 @@
* formats, and succeeds or fails correctly for optional attributes.
*/
TEST_F(GraphicsComposerHidlTest, GetDisplayAttribute) {
- std::vector<Config> configs =
- mComposerClient->getDisplayConfigs(mPrimaryDisplay);
- for (auto config : configs) {
- const std::array<IComposerClient::Attribute, 3> requiredAttributes = {{
- IComposerClient::Attribute::WIDTH, IComposerClient::Attribute::HEIGHT,
- IComposerClient::Attribute::VSYNC_PERIOD,
- }};
- for (auto attribute : requiredAttributes) {
- mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, attribute);
- }
+ std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
+ for (auto config : configs) {
+ const std::array<IComposerClient::Attribute, 3> requiredAttributes = {{
+ IComposerClient::Attribute::WIDTH, IComposerClient::Attribute::HEIGHT,
+ IComposerClient::Attribute::VSYNC_PERIOD,
+ }};
+ for (auto attribute : requiredAttributes) {
+ mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, attribute);
+ }
- const std::array<IComposerClient::Attribute, 2> optionalAttributes = {{
- IComposerClient::Attribute::DPI_X, IComposerClient::Attribute::DPI_Y,
- }};
- for (auto attribute : optionalAttributes) {
- mComposerClient->getRaw()->getDisplayAttribute(
- mPrimaryDisplay, config, attribute,
- [&](const auto& tmpError, const auto&) {
- EXPECT_TRUE(tmpError == Error::NONE ||
- tmpError == Error::UNSUPPORTED);
- });
+ const std::array<IComposerClient::Attribute, 2> optionalAttributes = {{
+ IComposerClient::Attribute::DPI_X, IComposerClient::Attribute::DPI_Y,
+ }};
+ for (auto attribute : optionalAttributes) {
+ mComposerClient->getRaw()->getDisplayAttribute(
+ mPrimaryDisplay, config, attribute, [&](const auto& tmpError, const auto&) {
+ EXPECT_TRUE(tmpError == Error::NONE || tmpError == Error::UNSUPPORTED);
+ });
+ }
}
- }
}
/**
* Test IComposerClient::getHdrCapabilities.
*/
TEST_F(GraphicsComposerHidlTest, GetHdrCapabilities) {
- float maxLuminance;
- float maxAverageLuminance;
- float minLuminance;
- mComposerClient->getHdrCapabilities(mPrimaryDisplay, &maxLuminance,
- &maxAverageLuminance, &minLuminance);
+ float maxLuminance;
+ float maxAverageLuminance;
+ float minLuminance;
+ mComposerClient->getHdrCapabilities(mPrimaryDisplay, &maxLuminance, &maxAverageLuminance,
+ &minLuminance);
}
/**
* Test IComposerClient::setClientTargetSlotCount.
*/
TEST_F(GraphicsComposerHidlTest, SetClientTargetSlotCount) {
- mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount);
+ mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount);
}
/**
@@ -284,12 +279,11 @@
* configs.
*/
TEST_F(GraphicsComposerHidlTest, SetActiveConfig) {
- std::vector<Config> configs =
- mComposerClient->getDisplayConfigs(mPrimaryDisplay);
- for (auto config : configs) {
- mComposerClient->setActiveConfig(mPrimaryDisplay, config);
- ASSERT_EQ(config, mComposerClient->getActiveConfig(mPrimaryDisplay));
- }
+ std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
+ for (auto config : configs) {
+ mComposerClient->setActiveConfig(mPrimaryDisplay, config);
+ ASSERT_EQ(config, mComposerClient->getActiveConfig(mPrimaryDisplay));
+ }
}
/**
@@ -298,11 +292,10 @@
* Test that IComposerClient::setColorMode succeeds for all color modes.
*/
TEST_F(GraphicsComposerHidlTest, SetColorMode) {
- std::vector<ColorMode> modes =
- mComposerClient->getColorModes(mPrimaryDisplay);
- for (auto mode : modes) {
- mComposerClient->setColorMode(mPrimaryDisplay, mode);
- }
+ std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay);
+ for (auto mode : modes) {
+ mComposerClient->setColorMode(mPrimaryDisplay, mode);
+ }
}
/**
@@ -311,20 +304,20 @@
* Test that IComposerClient::setPowerMode succeeds for all power modes.
*/
TEST_F(GraphicsComposerHidlTest, SetPowerMode) {
- std::vector<IComposerClient::PowerMode> modes;
- modes.push_back(IComposerClient::PowerMode::OFF);
+ std::vector<IComposerClient::PowerMode> modes;
+ modes.push_back(IComposerClient::PowerMode::OFF);
- if (mComposerClient->getDozeSupport(mPrimaryDisplay)) {
- modes.push_back(IComposerClient::PowerMode::DOZE);
- modes.push_back(IComposerClient::PowerMode::DOZE_SUSPEND);
- }
+ if (mComposerClient->getDozeSupport(mPrimaryDisplay)) {
+ modes.push_back(IComposerClient::PowerMode::DOZE);
+ modes.push_back(IComposerClient::PowerMode::DOZE_SUSPEND);
+ }
- // push ON last
- modes.push_back(IComposerClient::PowerMode::ON);
+ // push ON last
+ modes.push_back(IComposerClient::PowerMode::ON);
- for (auto mode : modes) {
- mComposerClient->setPowerMode(mPrimaryDisplay, mode);
- }
+ for (auto mode : modes) {
+ mComposerClient->setPowerMode(mPrimaryDisplay, mode);
+ }
}
/**
@@ -334,369 +327,365 @@
* spurious vsync events.
*/
TEST_F(GraphicsComposerHidlTest, SetVsyncEnabled) {
- mComposerCallback->setVsyncAllowed(true);
+ mComposerCallback->setVsyncAllowed(true);
- mComposerClient->setVsyncEnabled(mPrimaryDisplay, true);
- usleep(60 * 1000);
- mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
+ mComposerClient->setVsyncEnabled(mPrimaryDisplay, true);
+ usleep(60 * 1000);
+ mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
- mComposerCallback->setVsyncAllowed(false);
+ mComposerCallback->setVsyncAllowed(false);
}
// Tests for IComposerClient::Command.
class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest {
- protected:
- void SetUp() override {
- ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp());
+ protected:
+ void SetUp() override {
+ ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp());
- ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
+ ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
- mWriter = std::make_unique<CommandWriterBase>(1024);
- mReader = std::make_unique<TestCommandReader>();
- }
+ mWriter = std::make_unique<CommandWriterBase>(1024);
+ mReader = std::make_unique<TestCommandReader>();
+ }
- void TearDown() override {
- ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown());
- }
+ void TearDown() override { ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown()); }
- const native_handle_t* allocate() {
- IMapper::BufferDescriptorInfo info{};
- info.width = 64;
- info.height = 64;
- info.layerCount = 1;
- info.format = PixelFormat::RGBA_8888;
- info.usage = static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN |
- BufferUsage::CPU_READ_OFTEN);
+ const native_handle_t* allocate() {
+ IMapper::BufferDescriptorInfo info{};
+ info.width = 64;
+ info.height = 64;
+ info.layerCount = 1;
+ info.format = PixelFormat::RGBA_8888;
+ info.usage =
+ static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
- return mGralloc->allocate(info);
- }
+ return mGralloc->allocate(info);
+ }
- void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
+ void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
- std::unique_ptr<CommandWriterBase> mWriter;
- std::unique_ptr<TestCommandReader> mReader;
+ std::unique_ptr<CommandWriterBase> mWriter;
+ std::unique_ptr<TestCommandReader> mReader;
- private:
- std::unique_ptr<Gralloc> mGralloc;
+ private:
+ std::unique_ptr<Gralloc> mGralloc;
};
/**
* Test IComposerClient::Command::SET_COLOR_TRANSFORM.
*/
TEST_F(GraphicsComposerHidlCommandTest, SET_COLOR_TRANSFORM) {
- const std::array<float, 16> identity = {{
- 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,
- }};
+ const std::array<float, 16> identity = {{
+ 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,
+ }};
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->setColorTransform(identity.data(), ColorTransform::IDENTITY);
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->setColorTransform(identity.data(), ColorTransform::IDENTITY);
- execute();
+ execute();
}
/**
* Test IComposerClient::Command::SET_CLIENT_TARGET.
*/
TEST_F(GraphicsComposerHidlCommandTest, SET_CLIENT_TARGET) {
- mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount);
+ mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount);
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->setClientTarget(0, nullptr, -1, Dataspace::UNKNOWN,
- std::vector<IComposerClient::Rect>());
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->setClientTarget(0, nullptr, -1, Dataspace::UNKNOWN,
+ std::vector<IComposerClient::Rect>());
- execute();
+ execute();
}
/**
* Test IComposerClient::Command::SET_OUTPUT_BUFFER.
*/
TEST_F(GraphicsComposerHidlCommandTest, SET_OUTPUT_BUFFER) {
- if (mComposerClient->getMaxVirtualDisplayCount() == 0) {
- GTEST_SUCCEED() << "no virtual display support";
- return;
- }
+ if (mComposerClient->getMaxVirtualDisplayCount() == 0) {
+ GTEST_SUCCEED() << "no virtual display support";
+ return;
+ }
- Display display;
- PixelFormat format;
- ASSERT_NO_FATAL_FAILURE(display = mComposerClient->createVirtualDisplay(
- 64, 64, PixelFormat::IMPLEMENTATION_DEFINED,
- kBufferSlotCount, &format));
+ Display display;
+ PixelFormat format;
+ ASSERT_NO_FATAL_FAILURE(
+ display = mComposerClient->createVirtualDisplay(64, 64, PixelFormat::IMPLEMENTATION_DEFINED,
+ kBufferSlotCount, &format));
- const native_handle_t* handle;
- ASSERT_NO_FATAL_FAILURE(handle = allocate());
+ const native_handle_t* handle;
+ ASSERT_NO_FATAL_FAILURE(handle = allocate());
- mWriter->selectDisplay(display);
- mWriter->setOutputBuffer(0, handle, -1);
- execute();
+ mWriter->selectDisplay(display);
+ mWriter->setOutputBuffer(0, handle, -1);
+ execute();
}
/**
* Test IComposerClient::Command::VALIDATE_DISPLAY.
*/
TEST_F(GraphicsComposerHidlCommandTest, VALIDATE_DISPLAY) {
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->validateDisplay();
- execute();
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->validateDisplay();
+ execute();
}
/**
* Test IComposerClient::Command::ACCEPT_DISPLAY_CHANGES.
*/
TEST_F(GraphicsComposerHidlCommandTest, ACCEPT_DISPLAY_CHANGES) {
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->validateDisplay();
- mWriter->acceptDisplayChanges();
- execute();
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->validateDisplay();
+ mWriter->acceptDisplayChanges();
+ execute();
}
/**
* Test IComposerClient::Command::PRESENT_DISPLAY.
*/
TEST_F(GraphicsComposerHidlCommandTest, PRESENT_DISPLAY) {
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->validateDisplay();
- mWriter->presentDisplay();
- execute();
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->validateDisplay();
+ mWriter->presentDisplay();
+ execute();
}
/**
* Test IComposerClient::Command::SET_LAYER_CURSOR_POSITION.
*/
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_CURSOR_POSITION) {
- Layer layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+ Layer layer;
+ ASSERT_NO_FATAL_FAILURE(layer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->selectLayer(layer);
- mWriter->setLayerCursorPosition(1, 1);
- mWriter->setLayerCursorPosition(0, 0);
- execute();
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerCursorPosition(1, 1);
+ mWriter->setLayerCursorPosition(0, 0);
+ execute();
}
/**
* Test IComposerClient::Command::SET_LAYER_BUFFER.
*/
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_BUFFER) {
- auto handle = allocate();
- ASSERT_NE(nullptr, handle);
+ auto handle = allocate();
+ ASSERT_NE(nullptr, handle);
- Layer layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+ Layer layer;
+ ASSERT_NO_FATAL_FAILURE(layer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->selectLayer(layer);
- mWriter->setLayerBuffer(0, handle, -1);
- execute();
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerBuffer(0, handle, -1);
+ execute();
}
/**
* Test IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE.
*/
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SURFACE_DAMAGE) {
- Layer layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+ Layer layer;
+ ASSERT_NO_FATAL_FAILURE(layer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
- IComposerClient::Rect empty{0, 0, 0, 0};
- IComposerClient::Rect unit{0, 0, 1, 1};
+ IComposerClient::Rect empty{0, 0, 0, 0};
+ IComposerClient::Rect unit{0, 0, 1, 1};
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->selectLayer(layer);
- mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, empty));
- mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, unit));
- mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>());
- execute();
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, empty));
+ mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, unit));
+ mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>());
+ execute();
}
/**
* Test IComposerClient::Command::SET_LAYER_BLEND_MODE.
*/
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_BLEND_MODE) {
- Layer layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+ Layer layer;
+ ASSERT_NO_FATAL_FAILURE(layer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->selectLayer(layer);
- mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
- mWriter->setLayerBlendMode(IComposerClient::BlendMode::PREMULTIPLIED);
- mWriter->setLayerBlendMode(IComposerClient::BlendMode::COVERAGE);
- execute();
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
+ mWriter->setLayerBlendMode(IComposerClient::BlendMode::PREMULTIPLIED);
+ mWriter->setLayerBlendMode(IComposerClient::BlendMode::COVERAGE);
+ execute();
}
/**
* Test IComposerClient::Command::SET_LAYER_COLOR.
*/
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_COLOR) {
- Layer layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+ Layer layer;
+ ASSERT_NO_FATAL_FAILURE(layer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->selectLayer(layer);
- mWriter->setLayerColor(IComposerClient::Color{0xff, 0xff, 0xff, 0xff});
- mWriter->setLayerColor(IComposerClient::Color{0, 0, 0, 0});
- execute();
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerColor(IComposerClient::Color{0xff, 0xff, 0xff, 0xff});
+ mWriter->setLayerColor(IComposerClient::Color{0, 0, 0, 0});
+ execute();
}
/**
* Test IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE.
*/
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_COMPOSITION_TYPE) {
- Layer layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+ Layer layer;
+ ASSERT_NO_FATAL_FAILURE(layer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->selectLayer(layer);
- mWriter->setLayerCompositionType(IComposerClient::Composition::CLIENT);
- mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
- mWriter->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR);
- mWriter->setLayerCompositionType(IComposerClient::Composition::CURSOR);
- execute();
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerCompositionType(IComposerClient::Composition::CLIENT);
+ mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
+ mWriter->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR);
+ mWriter->setLayerCompositionType(IComposerClient::Composition::CURSOR);
+ execute();
}
/**
* Test IComposerClient::Command::SET_LAYER_DATASPACE.
*/
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_DATASPACE) {
- Layer layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+ Layer layer;
+ ASSERT_NO_FATAL_FAILURE(layer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->selectLayer(layer);
- mWriter->setLayerDataspace(Dataspace::UNKNOWN);
- execute();
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerDataspace(Dataspace::UNKNOWN);
+ execute();
}
/**
* Test IComposerClient::Command::SET_LAYER_DISPLAY_FRAME.
*/
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_DISPLAY_FRAME) {
- Layer layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+ Layer layer;
+ ASSERT_NO_FATAL_FAILURE(layer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->selectLayer(layer);
- mWriter->setLayerDisplayFrame(IComposerClient::Rect{0, 0, 1, 1});
- execute();
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerDisplayFrame(IComposerClient::Rect{0, 0, 1, 1});
+ execute();
}
/**
* Test IComposerClient::Command::SET_LAYER_PLANE_ALPHA.
*/
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_PLANE_ALPHA) {
- Layer layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+ Layer layer;
+ ASSERT_NO_FATAL_FAILURE(layer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->selectLayer(layer);
- mWriter->setLayerPlaneAlpha(0.0f);
- mWriter->setLayerPlaneAlpha(1.0f);
- execute();
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerPlaneAlpha(0.0f);
+ mWriter->setLayerPlaneAlpha(1.0f);
+ execute();
}
/**
* Test IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM.
*/
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SIDEBAND_STREAM) {
- if (!mComposer->hasCapability(IComposer::Capability::SIDEBAND_STREAM)) {
- GTEST_SUCCEED() << "no sideband stream support";
- return;
- }
+ if (!mComposer->hasCapability(IComposer::Capability::SIDEBAND_STREAM)) {
+ GTEST_SUCCEED() << "no sideband stream support";
+ return;
+ }
- auto handle = allocate();
- ASSERT_NE(nullptr, handle);
+ auto handle = allocate();
+ ASSERT_NE(nullptr, handle);
- Layer layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+ Layer layer;
+ ASSERT_NO_FATAL_FAILURE(layer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->selectLayer(layer);
- mWriter->setLayerSidebandStream(handle);
- execute();
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerSidebandStream(handle);
+ execute();
}
/**
* Test IComposerClient::Command::SET_LAYER_SOURCE_CROP.
*/
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SOURCE_CROP) {
- Layer layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+ Layer layer;
+ ASSERT_NO_FATAL_FAILURE(layer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->selectLayer(layer);
- mWriter->setLayerSourceCrop(IComposerClient::FRect{0.0f, 0.0f, 1.0f, 1.0f});
- execute();
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerSourceCrop(IComposerClient::FRect{0.0f, 0.0f, 1.0f, 1.0f});
+ execute();
}
/**
* Test IComposerClient::Command::SET_LAYER_TRANSFORM.
*/
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_TRANSFORM) {
- Layer layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+ Layer layer;
+ ASSERT_NO_FATAL_FAILURE(layer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->selectLayer(layer);
- mWriter->setLayerTransform(static_cast<Transform>(0));
- mWriter->setLayerTransform(Transform::FLIP_H);
- mWriter->setLayerTransform(Transform::FLIP_V);
- mWriter->setLayerTransform(Transform::ROT_90);
- mWriter->setLayerTransform(Transform::ROT_180);
- mWriter->setLayerTransform(Transform::ROT_270);
- mWriter->setLayerTransform(
- static_cast<Transform>(Transform::FLIP_H | Transform::ROT_90));
- mWriter->setLayerTransform(
- static_cast<Transform>(Transform::FLIP_V | Transform::ROT_90));
- execute();
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerTransform(static_cast<Transform>(0));
+ mWriter->setLayerTransform(Transform::FLIP_H);
+ mWriter->setLayerTransform(Transform::FLIP_V);
+ mWriter->setLayerTransform(Transform::ROT_90);
+ mWriter->setLayerTransform(Transform::ROT_180);
+ mWriter->setLayerTransform(Transform::ROT_270);
+ mWriter->setLayerTransform(static_cast<Transform>(Transform::FLIP_H | Transform::ROT_90));
+ mWriter->setLayerTransform(static_cast<Transform>(Transform::FLIP_V | Transform::ROT_90));
+ execute();
}
/**
* Test IComposerClient::Command::SET_LAYER_VISIBLE_REGION.
*/
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_VISIBLE_REGION) {
- Layer layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+ Layer layer;
+ ASSERT_NO_FATAL_FAILURE(layer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
- IComposerClient::Rect empty{0, 0, 0, 0};
- IComposerClient::Rect unit{0, 0, 1, 1};
+ IComposerClient::Rect empty{0, 0, 0, 0};
+ IComposerClient::Rect unit{0, 0, 1, 1};
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->selectLayer(layer);
- mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, empty));
- mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, unit));
- mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>());
- execute();
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, empty));
+ mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, unit));
+ mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>());
+ execute();
}
/**
* Test IComposerClient::Command::SET_LAYER_Z_ORDER.
*/
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_Z_ORDER) {
- Layer layer;
- ASSERT_NO_FATAL_FAILURE(
- layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+ Layer layer;
+ ASSERT_NO_FATAL_FAILURE(layer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
- mWriter->selectDisplay(mPrimaryDisplay);
- mWriter->selectLayer(layer);
- mWriter->setLayerZOrder(10);
- mWriter->setLayerZOrder(0);
- execute();
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerZOrder(10);
+ mWriter->setLayerZOrder(0);
+ execute();
}
-} // namespace anonymous
-} // namespace tests
+} // namespace
+} // namespace vts
} // namespace V2_1
} // namespace composer
} // namespace graphics
@@ -704,7 +693,7 @@
} // namespace android
int main(int argc, char** argv) {
- using android::hardware::graphics::composer::V2_1::tests::GraphicsComposerHidlEnvironment;
+ using android::hardware::graphics::composer::V2_1::vts::GraphicsComposerHidlEnvironment;
::testing::AddGlobalTestEnvironment(GraphicsComposerHidlEnvironment::Instance());
::testing::InitGoogleTest(&argc, argv);
GraphicsComposerHidlEnvironment::Instance()->init(&argc, argv);
diff --git a/graphics/composer/2.2/default/Android.bp b/graphics/composer/2.2/default/Android.bp
new file mode 100644
index 0000000..906479e
--- /dev/null
+++ b/graphics/composer/2.2/default/Android.bp
@@ -0,0 +1,31 @@
+cc_binary {
+ name: "android.hardware.graphics.composer@2.2-service",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ relative_install_path: "hw",
+ srcs: ["service.cpp"],
+ init_rc: ["android.hardware.graphics.composer@2.2-service.rc"],
+ header_libs: [
+ "android.hardware.graphics.composer@2.2-passthrough",
+ ],
+ shared_libs: [
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.2",
+ "android.hardware.graphics.mapper@2.0",
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "libfmq",
+ "libhardware",
+ "libhidlbase",
+ "libhidltransport",
+ "libhwc2on1adapter",
+ "libhwc2onfbadapter",
+ "liblog",
+ "libsync",
+ "libutils",
+ ],
+ cflags: [
+ "-DLOG_TAG=\"ComposerHal\""
+ ],
+}
diff --git a/graphics/composer/2.2/default/OWNERS b/graphics/composer/2.2/default/OWNERS
new file mode 100644
index 0000000..4714be2
--- /dev/null
+++ b/graphics/composer/2.2/default/OWNERS
@@ -0,0 +1,5 @@
+# Graphics team
+courtneygo@google.com
+jessehall@google.com
+olv@google.com
+stoza@google.com
diff --git a/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc b/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
new file mode 100644
index 0000000..a41d902
--- /dev/null
+++ b/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
@@ -0,0 +1,6 @@
+service vendor.hwcomposer-2-2 /vendor/bin/hw/android.hardware.graphics.composer@2.2-service
+ class hal animation
+ user system
+ group graphics drmrpc
+ capabilities SYS_NICE
+ onrestart restart surfaceflinger
diff --git a/graphics/composer/2.2/default/service.cpp b/graphics/composer/2.2/default/service.cpp
new file mode 100644
index 0000000..8c5ef18
--- /dev/null
+++ b/graphics/composer/2.2/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.2/IComposer.h>
+#include <binder/ProcessState.h>
+#include <composer-passthrough/2.2/HwcLoader.h>
+#include <hidl/HidlTransportSupport.h>
+
+using android::hardware::graphics::composer::V2_2::IComposer;
+using android::hardware::graphics::composer::V2_2::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/graphics/composer/2.2/utils/hal/Android.bp b/graphics/composer/2.2/utils/hal/Android.bp
new file mode 100644
index 0000000..10dcae4
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/Android.bp
@@ -0,0 +1,35 @@
+//
+// 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.2-hal",
+ defaults: ["hidl_defaults"],
+ vendor_available: true,
+ shared_libs: [
+ "android.hardware.graphics.composer@2.2",
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.graphics.composer@2.2",
+ ],
+ header_libs: [
+ "android.hardware.graphics.composer@2.2-command-buffer",
+ "android.hardware.graphics.composer@2.1-hal",
+ ],
+ export_header_lib_headers: [
+ "android.hardware.graphics.composer@2.2-command-buffer",
+ "android.hardware.graphics.composer@2.1-hal",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/Composer.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/Composer.h
new file mode 100644
index 0000000..58bbaa5
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/Composer.h
@@ -0,0 +1,74 @@
+/*
+ * 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 "Composer.h included without LOG_TAG"
+#endif
+
+#include <android/hardware/graphics/composer/2.2/IComposer.h>
+#include <composer-hal/2.1/Composer.h>
+#include <composer-hal/2.2/ComposerClient.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+namespace detail {
+
+// ComposerImpl implements V2_*::IComposer on top of V2_*::ComposerHal
+template <typename Interface, typename Hal>
+class ComposerImpl : public V2_1::hal::detail::ComposerImpl<Interface, Hal> {
+ 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) : BaseType2_1(std::move(hal)) {}
+
+ protected:
+ V2_1::IComposerClient* createClient() override {
+ auto client = ComposerClient::create(mHal.get());
+ if (!client) {
+ return nullptr;
+ }
+
+ auto clientDestroyed = [this]() { onClientDestroyed(); };
+ client->setOnClientDestroyed(clientDestroyed);
+
+ return client.release();
+ }
+
+ private:
+ using BaseType2_1 = V2_1::hal::detail::ComposerImpl<Interface, Hal>;
+ using BaseType2_1::mHal;
+ using BaseType2_1::onClientDestroyed;
+};
+
+} // namespace detail
+
+using Composer = detail::ComposerImpl<IComposer, ComposerHal>;
+
+} // namespace hal
+} // namespace V2_2
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h
new file mode 100644
index 0000000..d550f83
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h
@@ -0,0 +1,162 @@
+/*
+ * 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 <android/hardware/graphics/composer/2.2/IComposerClient.h>
+#include <composer-hal/2.1/ComposerClient.h>
+#include <composer-hal/2.2/ComposerCommandEngine.h>
+#include <composer-hal/2.2/ComposerHal.h>
+#include <composer-hal/2.2/ComposerResources.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+namespace detail {
+
+// ComposerClientImpl implements V2_*::IComposerClient on top of V2_*::ComposerHal
+template <typename Interface, typename Hal>
+class ComposerClientImpl : public V2_1::hal::detail::ComposerClientImpl<Interface, Hal> {
+ 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) : BaseType2_1(hal) {}
+
+ // IComposerClient 2.2 interface
+
+ Return<void> getPerFrameMetadataKeys(
+ Display display, IComposerClient::getPerFrameMetadataKeys_cb hidl_cb) override {
+ std::vector<IComposerClient::PerFrameMetadataKey> keys;
+ Error error = mHal->getPerFrameMetadataKeys(display, &keys);
+ hidl_cb(error, keys);
+ return Void();
+ }
+
+ Return<void> getReadbackBufferAttributes(
+ Display display, IComposerClient::getReadbackBufferAttributes_cb hidl_cb) override {
+ PixelFormat format = static_cast<PixelFormat>(0);
+ Dataspace dataspace = Dataspace::UNKNOWN;
+ Error error = mHal->getReadbackBufferAttributes(display, &format, &dataspace);
+ hidl_cb(error, format, dataspace);
+ return Void();
+ }
+
+ Return<void> getReadbackBufferFence(
+ Display display, IComposerClient::getReadbackBufferFence_cb hidl_cb) override {
+ base::unique_fd fenceFd;
+ Error error = mHal->getReadbackBufferFence(display, &fenceFd);
+ if (error != Error::NONE) {
+ hidl_cb(error, nullptr);
+ return Void();
+ }
+
+ NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
+ hidl_cb(error, getFenceHandle(fenceFd, fenceStorage));
+ return Void();
+ }
+
+ Return<Error> setReadbackBuffer(Display display, const hidl_handle& buffer,
+ const hidl_handle& releaseFence) override {
+ base::unique_fd fenceFd;
+ Error error = getFenceFd(releaseFence, &fenceFd);
+ if (error != Error::NONE) {
+ return error;
+ }
+
+ auto resources = static_cast<ComposerResources*>(mResources.get());
+ const native_handle_t* readbackBuffer;
+ ComposerResources::ReplacedBufferHandle replacedReadbackBuffer;
+ error = resources->getDisplayReadbackBuffer(display, buffer.getNativeHandle(),
+ &readbackBuffer, &replacedReadbackBuffer);
+ if (error != Error::NONE) {
+ return error;
+ }
+
+ return mHal->setReadbackBuffer(display, readbackBuffer, std::move(fenceFd));
+ }
+
+ Return<Error> setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) override {
+ return mHal->setPowerMode_2_2(display, mode);
+ }
+
+ protected:
+ std::unique_ptr<V2_1::hal::ComposerResources> createResources() override {
+ return ComposerResources::create();
+ }
+
+ std::unique_ptr<V2_1::hal::ComposerCommandEngine> createCommandEngine() override {
+ return std::make_unique<ComposerCommandEngine>(
+ mHal, static_cast<ComposerResources*>(mResources.get()));
+ }
+
+ // convert fenceFd to or from hidl_handle
+ static Error getFenceFd(const hidl_handle& fenceHandle, base::unique_fd* outFenceFd) {
+ auto handle = fenceHandle.getNativeHandle();
+ if (handle && handle->numFds > 1) {
+ ALOGE("invalid fence handle with %d fds", handle->numFds);
+ return Error::BAD_PARAMETER;
+ }
+
+ int fenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
+ if (fenceFd >= 0) {
+ fenceFd = dup(fenceFd);
+ if (fenceFd < 0) {
+ return Error::NO_RESOURCES;
+ }
+ }
+
+ outFenceFd->reset(fenceFd);
+
+ return Error::NONE;
+ }
+
+ static hidl_handle getFenceHandle(const base::unique_fd& fenceFd, char* handleStorage) {
+ native_handle_t* handle = nullptr;
+ if (fenceFd >= 0) {
+ handle = native_handle_init(handleStorage, 1, 0);
+ handle->data[0] = fenceFd;
+ }
+
+ return hidl_handle(handle);
+ }
+
+ private:
+ using BaseType2_1 = V2_1::hal::detail::ComposerClientImpl<Interface, Hal>;
+ using BaseType2_1::mHal;
+ using BaseType2_1::mResources;
+};
+
+} // namespace detail
+
+using ComposerClient = detail::ComposerClientImpl<IComposerClient, ComposerHal>;
+
+} // namespace hal
+} // namespace V2_2
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h
new file mode 100644
index 0000000..adcac46
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h
@@ -0,0 +1,103 @@
+/*
+ * 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 <composer-command-buffer/2.2/ComposerCommandBuffer.h>
+#include <composer-hal/2.1/ComposerCommandEngine.h>
+#include <composer-hal/2.2/ComposerHal.h>
+#include <composer-hal/2.2/ComposerResources.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+class ComposerCommandEngine : public V2_1::hal::ComposerCommandEngine {
+ public:
+ ComposerCommandEngine(ComposerHal* hal, ComposerResources* resources)
+ : BaseType2_1(hal, resources), mHal(hal) {}
+
+ protected:
+ bool executeCommand(V2_1::IComposerClient::Command command, uint16_t length) override {
+ switch (static_cast<IComposerClient::Command>(command)) {
+ case IComposerClient::Command::SET_PER_FRAME_METADATA:
+ return executeSetPerFrameMetadata(length);
+ case IComposerClient::Command::SET_LAYER_FLOAT_COLOR:
+ return executeSetLayerFloatColor(length);
+ default:
+ return BaseType2_1::executeCommand(command, length);
+ }
+ }
+
+ bool executeSetPerFrameMetadata(uint16_t length) {
+ // (key, value) pairs
+ if (length % 2 != 0) {
+ return false;
+ }
+
+ std::vector<IComposerClient::PerFrameMetadata> metadata;
+ metadata.reserve(length / 2);
+ while (length > 0) {
+ metadata.emplace_back(IComposerClient::PerFrameMetadata{
+ static_cast<IComposerClient::PerFrameMetadataKey>(readSigned()), readFloat()});
+ length -= 2;
+ }
+
+ auto err = mHal->setPerFrameMetadata(mCurrentDisplay, metadata);
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerFloatColor(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerFloatColorLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerFloatColor(mCurrentDisplay, mCurrentLayer, readFloatColor());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ IComposerClient::FloatColor readFloatColor() {
+ return IComposerClient::FloatColor{readFloat(), readFloat(), readFloat(), readFloat()};
+ }
+
+ private:
+ using BaseType2_1 = V2_1::hal::ComposerCommandEngine;
+ using BaseType2_1::mWriter;
+
+ ComposerHal* mHal;
+};
+
+} // namespace hal
+} // namespace V2_2
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h
new file mode 100644
index 0000000..30b3643
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h
@@ -0,0 +1,66 @@
+/*
+ * 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 <android-base/unique_fd.h>
+#include <android/hardware/graphics/composer/2.2/IComposer.h>
+#include <android/hardware/graphics/composer/2.2/IComposerClient.h>
+#include <composer-hal/2.1/ComposerHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+using common::V1_0::Dataspace;
+using common::V1_0::PixelFormat;
+using V2_1::Display;
+using V2_1::Error;
+using V2_1::Layer;
+
+class ComposerHal : public V2_1::hal::ComposerHal {
+ public:
+ // superceded by setPowerMode_2_2
+ Error setPowerMode(Display display, V2_1::IComposerClient::PowerMode mode) override {
+ return setPowerMode_2_2(display, static_cast<IComposerClient::PowerMode>(mode));
+ }
+
+ virtual Error getPerFrameMetadataKeys(
+ Display display, std::vector<IComposerClient::PerFrameMetadataKey>* outKeys) = 0;
+ virtual Error setPerFrameMetadata(
+ Display display, const std::vector<IComposerClient::PerFrameMetadata>& metadata) = 0;
+
+ virtual Error getReadbackBufferAttributes(Display display, PixelFormat* outFormat,
+ Dataspace* outDataspace) = 0;
+ virtual Error setReadbackBuffer(Display display, const native_handle_t* bufferHandle,
+ base::unique_fd fenceFd) = 0;
+ virtual Error getReadbackBufferFence(Display display, base::unique_fd* outFenceFd) = 0;
+
+ virtual Error setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) = 0;
+
+ virtual Error setLayerFloatColor(Display display, Layer layer,
+ IComposerClient::FloatColor color) = 0;
+};
+
+} // namespace hal
+} // namespace V2_2
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerResources.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerResources.h
new file mode 100644
index 0000000..85b6651
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerResources.h
@@ -0,0 +1,105 @@
+/*
+ * 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 <composer-hal/2.1/ComposerResources.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+using V2_1::hal::ComposerHandleCache;
+using V2_1::hal::ComposerHandleImporter;
+
+class ComposerDisplayResource : public V2_1::hal::ComposerDisplayResource {
+ public:
+ ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer,
+ uint32_t outputBufferCacheSize)
+ : V2_1::hal::ComposerDisplayResource(type, importer, outputBufferCacheSize),
+ mReadbackBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, 1) {}
+
+ Error getReadbackBuffer(const native_handle_t* inHandle, const native_handle_t** outHandle,
+ const native_handle** outReplacedHandle) {
+ const uint32_t slot = 0;
+ const bool fromCache = false;
+ return mReadbackBufferCache.getHandle(slot, fromCache, inHandle, outHandle,
+ outReplacedHandle);
+ }
+
+ protected:
+ ComposerHandleCache mReadbackBufferCache;
+};
+
+class ComposerResources : public V2_1::hal::ComposerResources {
+ public:
+ static std::unique_ptr<ComposerResources> create() {
+ auto resources = std::make_unique<ComposerResources>();
+ return resources->init() ? std::move(resources) : nullptr;
+ }
+
+ Error getDisplayReadbackBuffer(Display display, const native_handle_t* rawHandle,
+ const native_handle_t** outHandle,
+ ReplacedBufferHandle* outReplacedHandle) {
+ // import buffer
+ const native_handle_t* importedHandle;
+ Error error = mImporter.importBuffer(rawHandle, &importedHandle);
+ if (error != Error::NONE) {
+ return error;
+ }
+
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+
+ auto iter = mDisplayResources.find(display);
+ if (iter == mDisplayResources.end()) {
+ mImporter.freeBuffer(importedHandle);
+ return Error::BAD_DISPLAY;
+ }
+ ComposerDisplayResource& displayResource =
+ *static_cast<ComposerDisplayResource*>(iter->second.get());
+
+ // update cache
+ const native_handle_t* replacedHandle;
+ error = displayResource.getReadbackBuffer(importedHandle, outHandle, &replacedHandle);
+ if (error != Error::NONE) {
+ mImporter.freeBuffer(importedHandle);
+ return error;
+ }
+
+ outReplacedHandle->reset(&mImporter, replacedHandle);
+ return Error::NONE;
+ }
+
+ protected:
+ std::unique_ptr<V2_1::hal::ComposerDisplayResource> createDisplayResource(
+ ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) override {
+ return std::make_unique<ComposerDisplayResource>(type, mImporter, outputBufferCacheSize);
+ }
+};
+
+} // namespace hal
+} // namespace V2_2
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.2/utils/passthrough/Android.bp b/graphics/composer/2.2/utils/passthrough/Android.bp
new file mode 100644
index 0000000..318ce91
--- /dev/null
+++ b/graphics/composer/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/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h
new file mode 100644
index 0000000..b251351
--- /dev/null
+++ b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h
@@ -0,0 +1,208 @@
+/*
+ * 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_0::Dataspace;
+using common::V1_0::PixelFormat;
+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 setPerFrameMetadata(
+ Display display, const std::vector<IComposerClient::PerFrameMetadata>& metadata) override {
+ if (!mDispatch.setPerFrameMetadata) {
+ 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.setPerFrameMetadata(mDevice, display, 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 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);
+ }
+
+ 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_PER_FRAME_METADATA, &mDispatch.setPerFrameMetadata);
+ 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);
+
+ return true;
+ }
+
+ struct {
+ HWC2_PFN_SET_LAYER_FLOAT_COLOR setLayerFloatColor;
+ HWC2_PFN_SET_PER_FRAME_METADATA setPerFrameMetadata;
+ 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;
+ } mDispatch = {};
+
+ private:
+ using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl<Hal>;
+ using BaseType2_1::mDevice;
+ 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/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h
new file mode 100644
index 0000000..cb4a238
--- /dev/null
+++ b/graphics/composer/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/graphics/composer/2.2/utils/vts/Android.bp b/graphics/composer/2.2/utils/vts/Android.bp
new file mode 100644
index 0000000..641fdcb
--- /dev/null
+++ b/graphics/composer/2.2/utils/vts/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_static {
+ name: "android.hardware.graphics.composer@2.2-vts",
+ defaults: ["hidl_defaults"],
+ srcs: [
+ "ComposerVts.cpp",
+ ],
+ static_libs: [
+ "VtsHalHidlTargetTestBase",
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.1-vts",
+ "android.hardware.graphics.composer@2.2",
+ ],
+ header_libs: [
+ "android.hardware.graphics.composer@2.1-command-buffer",
+ "android.hardware.graphics.composer@2.2-command-buffer",
+ ],
+ cflags: [
+ "-O0",
+ "-g",
+ "-DLOG_TAG=\"ComposerVts\"",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerTestUtils.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
similarity index 96%
rename from graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerTestUtils.cpp
rename to graphics/composer/2.2/utils/vts/ComposerVts.cpp
index 00946ce..b536f67 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerTestUtils.cpp
+++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
@@ -14,22 +14,22 @@
* limitations under the License.
*/
-#include <VtsHalHidlTargetTestBase.h>
-#include <hidl/HidlTransportUtils.h>
+#include <composer-vts/2.2/ComposerVts.h>
+#include <VtsHalHidlTargetTestBase.h>
#include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
-#include "2.2/VtsHalGraphicsComposerTestUtils.h"
+#include <hidl/HidlTransportUtils.h>
namespace android {
namespace hardware {
namespace graphics {
namespace composer {
namespace V2_2 {
-namespace tests {
+namespace vts {
-using android::hardware::graphics::composer::V2_2::IComposerClient;
-using android::hardware::details::getDescriptor;
using android::hardware::details::canCastInterface;
+using android::hardware::details::getDescriptor;
+using android::hardware::graphics::composer::V2_2::IComposerClient;
std::unique_ptr<ComposerClient_v2_2> Composer_v2_2::createClient_v2_2() {
std::unique_ptr<ComposerClient_v2_2> client;
@@ -56,7 +56,7 @@
return keys;
}
-void ComposerClient_v2_2::execute_v2_2(V2_1::tests::TestCommandReader* reader,
+void ComposerClient_v2_2::execute_v2_2(V2_1::vts::TestCommandReader* reader,
V2_2::CommandWriterBase* writer) {
bool queueChanged = false;
uint32_t commandLength = 0;
@@ -119,7 +119,7 @@
*outFence = 0;
}
-} // namespace tests
+} // namespace vts
} // namespace V2_2
} // namespace composer
} // namespace graphics
diff --git a/graphics/composer/2.2/vts/functional/include/2.2/VtsHalGraphicsComposerTestUtils.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
similarity index 82%
rename from graphics/composer/2.2/vts/functional/include/2.2/VtsHalGraphicsComposerTestUtils.h
rename to graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
index c5756ed..eced69f 100644
--- a/graphics/composer/2.2/vts/functional/include/2.2/VtsHalGraphicsComposerTestUtils.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
@@ -22,11 +22,11 @@
#include <unordered_set>
#include <vector>
-#include <VtsHalGraphicsComposerTestUtils.h>
#include <VtsHalHidlTargetTestBase.h>
#include <android/hardware/graphics/composer/2.2/IComposer.h>
#include <android/hardware/graphics/composer/2.2/IComposerClient.h>
#include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
+#include <composer-vts/2.1/ComposerVts.h>
#include <utils/StrongPointer.h>
namespace android {
@@ -34,7 +34,7 @@
namespace graphics {
namespace composer {
namespace V2_2 {
-namespace tests {
+namespace vts {
using android::hardware::graphics::common::V1_0::ColorMode;
using android::hardware::graphics::common::V1_0::Dataspace;
@@ -47,22 +47,22 @@
// Only thing I need for Composer_v2_2 is to create a v2_2 ComposerClient
// Everything else is the same
-class Composer_v2_2 : public V2_1::tests::Composer {
+class Composer_v2_2 : public V2_1::vts::Composer {
public:
- Composer_v2_2() : V2_1::tests::Composer(){};
- explicit Composer_v2_2(const std::string& name) : V2_1::tests::Composer(name){};
+ Composer_v2_2() : V2_1::vts::Composer(){};
+ explicit Composer_v2_2(const std::string& name) : V2_1::vts::Composer(name){};
std::unique_ptr<ComposerClient_v2_2> createClient_v2_2();
};
// A wrapper to IComposerClient.
class ComposerClient_v2_2
- : public android::hardware::graphics::composer::V2_1::tests::ComposerClient {
+ : public android::hardware::graphics::composer::V2_1::vts::ComposerClient {
public:
ComposerClient_v2_2(const sp<IComposerClient>& client)
- : V2_1::tests::ComposerClient(client), mClient_v2_2(client){};
+ : V2_1::vts::ComposerClient(client), mClient_v2_2(client){};
- void execute_v2_2(V2_1::tests::TestCommandReader* reader, V2_2::CommandWriterBase* writer);
+ void execute_v2_2(V2_1::vts::TestCommandReader* reader, V2_2::CommandWriterBase* writer);
std::vector<IComposerClient::PerFrameMetadataKey> getPerFrameMetadataKeys(Display display);
@@ -76,7 +76,7 @@
sp<V2_2::IComposerClient> mClient_v2_2;
};
-} // namespace tests
+} // namespace vts
} // namespace V2_2
} // namespace composer
} // namespace graphics
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index 78322a1..7747900 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -14,37 +14,6 @@
// limitations under the License.
//
-cc_library_static {
- name: "libVtsHalGraphicsComposerTestUtils@2.2",
- defaults: ["hidl_defaults"],
- srcs: [
- "VtsHalGraphicsComposerTestUtils.cpp",
- ],
- shared_libs: [
- "android.hardware.graphics.composer@2.1",
- "android.hardware.graphics.composer@2.2",
- "libfmq",
- "libsync",
- ],
- static_libs: [
- "libVtsHalGraphicsComposerTestUtils",
- "VtsHalHidlTargetTestBase",
- ],
- header_libs: [
- "android.hardware.graphics.composer@2.1-command-buffer",
- "android.hardware.graphics.composer@2.2-command-buffer",
- ],
- cflags: [
- "-Wall",
- "-Wextra",
- "-Werror",
- "-O0",
- "-g",
- "-DLOG_TAG=\"GraphicsComposerTestUtils@2.2\"",
- ],
- export_include_dirs: ["include"],
-}
-
cc_test {
name: "VtsHalGraphicsComposerV2_2TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
@@ -58,14 +27,13 @@
],
static_libs: [
"android.hardware.graphics.allocator@2.0",
- "android.hardware.graphics.composer@2.2",
"android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.1-vts",
+ "android.hardware.graphics.composer@2.2",
+ "android.hardware.graphics.composer@2.2-vts",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.0-vts",
"android.hardware.graphics.mapper@2.1",
- "libVtsHalGraphicsComposerTestUtils",
- "libVtsHalGraphicsComposerTestUtils@2.2",
- "libnativehelper",
],
header_libs: [
"android.hardware.graphics.composer@2.1-command-buffer",
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index 6fbdd3c..c494329 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -16,23 +16,20 @@
#define LOG_TAG "graphics_composer_hidl_hal_test@2.2"
+#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
#include <android/hardware/graphics/mapper/2.1/IMapper.h>
+#include <composer-vts/2.1/GraphicsComposerCallback.h>
+#include <composer-vts/2.1/TestCommandReader.h>
+#include <composer-vts/2.2/ComposerVts.h>
#include <mapper-vts/2.0/MapperVts.h>
-#include <sync/sync.h>
-#include "2.2/VtsHalGraphicsComposerTestUtils.h"
-#include "GraphicsComposerCallback.h"
-#include "TestCommandReader.h"
-#include "VtsHalGraphicsComposerTestUtils.h"
-
-#include <VtsHalHidlTargetTestBase.h>
namespace android {
namespace hardware {
namespace graphics {
namespace composer {
namespace V2_2 {
-namespace tests {
+namespace vts {
namespace {
using android::hardware::graphics::common::V1_0::BufferUsage;
@@ -71,7 +68,7 @@
GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient_v2_2());
- mComposerCallback = new V2_1::tests::GraphicsComposerCallback;
+ mComposerCallback = new V2_1::vts::GraphicsComposerCallback;
mComposerClient->registerCallback(mComposerCallback);
// assume the first display is primary and is never removed
@@ -95,7 +92,7 @@
std::unique_ptr<Composer_v2_2> mComposer;
std::unique_ptr<ComposerClient_v2_2> mComposerClient;
- sp<V2_1::tests::GraphicsComposerCallback> mComposerCallback;
+ sp<V2_1::vts::GraphicsComposerCallback> mComposerCallback;
// the first display and is assumed never to be removed
Display mPrimaryDisplay;
@@ -122,7 +119,7 @@
ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
mWriter = std::make_unique<V2_2::CommandWriterBase>(1024);
- mReader = std::make_unique<V2_1::tests::TestCommandReader>();
+ mReader = std::make_unique<V2_1::vts::TestCommandReader>();
}
void TearDown() override { ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown()); }
@@ -142,7 +139,7 @@
void execute() { mComposerClient->execute_v2_2(mReader.get(), mWriter.get()); }
std::unique_ptr<V2_2::CommandWriterBase> mWriter;
- std::unique_ptr<V2_1::tests::TestCommandReader> mReader;
+ std::unique_ptr<V2_1::vts::TestCommandReader> mReader;
private:
std::unique_ptr<Gralloc> mGralloc;
@@ -239,7 +236,7 @@
}
} // namespace
-} // namespace tests
+} // namespace vts
} // namespace V2_2
} // namespace composer
} // namespace graphics
@@ -247,7 +244,7 @@
} // namespace android
int main(int argc, char** argv) {
- using android::hardware::graphics::composer::V2_2::tests::GraphicsComposerHidlEnvironment;
+ using android::hardware::graphics::composer::V2_2::vts::GraphicsComposerHidlEnvironment;
::testing::AddGlobalTestEnvironment(GraphicsComposerHidlEnvironment::Instance());
::testing::InitGoogleTest(&argc, argv);
GraphicsComposerHidlEnvironment::Instance()->init(&argc, argv);