From 830137fc08da2ce0d89cc1316d023f3de015ab6f Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Thu, 13 Sep 2018 17:19:38 -0700 Subject: [PATCH] [Graphics] Add setLayerColorTransform. This patch adds HAL API to set per-layer color transformation with a 4x4 matrix. Given a 4x4 matrix, the matrix will be applied on the current layer before composition. BUG: 111562338 Test: Build, flash and boot, run VtsHalGraphicsComposerV2_3TargetTest Change-Id: I673cfc2745d35947107dcab19f383ba5a8067605 --- graphics/composer/2.3/Android.bp | 1 + graphics/composer/2.3/IComposerClient.hal | 71 ++++++++++++++++ .../2.3/utils/command-buffer/Android.bp | 15 ++++ .../2.3/ComposerCommandBuffer.h | 76 +++++++++++++++++ graphics/composer/2.3/utils/hal/Android.bp | 2 + .../include/composer-hal/2.3/ComposerClient.h | 20 ++++- .../composer-hal/2.3/ComposerCommandEngine.h | 81 +++++++++++++++++++ .../include/composer-hal/2.3/ComposerHal.h | 2 + .../include/composer-passthrough/2.3/HwcHal.h | 11 +++ graphics/composer/2.3/utils/vts/Android.bp | 1 + .../composer/2.3/vts/functional/Android.bp | 1 + .../VtsHalGraphicsComposerV2_3TargetTest.cpp | 37 +++++++++ 12 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 graphics/composer/2.3/utils/command-buffer/Android.bp create mode 100644 graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h create mode 100644 graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerCommandEngine.h diff --git a/graphics/composer/2.3/Android.bp b/graphics/composer/2.3/Android.bp index 23061dda5b..78da099cfa 100644 --- a/graphics/composer/2.3/Android.bp +++ b/graphics/composer/2.3/Android.bp @@ -12,6 +12,7 @@ hidl_interface { ], interfaces: [ "android.hardware.graphics.common@1.0", + "android.hardware.graphics.common@1.1", "android.hardware.graphics.composer@2.1", "android.hardware.graphics.composer@2.2", "android.hidl.base@1.0", diff --git a/graphics/composer/2.3/IComposerClient.hal b/graphics/composer/2.3/IComposerClient.hal index 77dd3eed72..089438efac 100644 --- a/graphics/composer/2.3/IComposerClient.hal +++ b/graphics/composer/2.3/IComposerClient.hal @@ -16,12 +16,58 @@ package android.hardware.graphics.composer@2.3; +import android.hardware.graphics.composer@2.1::IComposerClient.Command; import @2.2::IComposerClient; import @2.1::Display; import @2.1::Error; interface IComposerClient extends @2.2::IComposerClient { + enum Command : @2.2::IComposerClient.Command { + /** + * SET_LAYER_COLOR_TRANSFORM has this pseudo prototype + * + * setLayerColorTransform(float[16] matrix); + * + * This command has the following binary layout in bytes: + * + * 0 - 16 * 4: matrix + * + * Sets a matrix for color transform which will be applied on this layer + * before composition. + * + * If the device is not capable of apply the matrix on this layer, it must force + * this layer to client composition during VALIDATE_DISPLAY. + * + * The matrix provided is an affine color transformation of the following + * form: + * + * |r.r r.g r.b 0| + * |g.r g.g g.b 0| + * |b.r b.g b.b 0| + * |Tr Tg Tb 1| + * + * This matrix must be provided in row-major form: + * + * {r.r, r.g, r.b, 0, g.r, ...}. + * + * Given a matrix of this form and an input color [R_in, G_in, B_in], + * the input color must first be converted to linear space + * [R_linear, G_linear, B_linear], then the output linear color + * [R_out_linear, G_out_linear, B_out_linear] will be: + * + * R_out_linear = R_linear * r.r + G_linear * g.r + B_linear * b.r + Tr + * G_out_linear = R_linear * r.g + G_linear * g.g + B_linear * b.g + Tg + * B_out_linear = R_linear * r.b + G_linear * g.b + B_linear * b.b + Tb + * + * [R_out_linear, G_out_linear, B_out_linear] must then be converted to + * gamma space: [R_out, G_out, B_out] before blending. + * + * @param matrix is a 4x4 transform matrix (16 floats) as described above. + */ + SET_LAYER_COLOR_TRANSFORM = 0x40d << @2.1::IComposerClient.Command:OPCODE_SHIFT, + }; + /** * Returns the port and data that describe a physical display. The port is * a unique number that identifies a physical connector (e.g. eDP, HDMI) @@ -42,4 +88,29 @@ interface IComposerClient extends @2.2::IComposerClient { uint8_t port, vec data); + /** + * Executes commands from the input command message queue. Return values + * generated by the input commands are written to the output command + * message queue in the form of value commands. + * + * @param inLength is the length of input commands. + * @param inHandles is an array of handles referenced by the input + * commands. + * @return error is NONE upon success. Otherwise, + * BAD_PARAMETER when inLength is not equal to the length of + * commands in the input command message queue. + * NO_RESOURCES when the output command message queue was not + * properly drained. + * @param outQueueChanged indicates whether the output command message + * queue has changed. + * @param outLength is the length of output commands. + * @param outHandles is an array of handles referenced by the output + * commands. + */ + executeCommands_2_3(uint32_t inLength, + vec inHandles) + generates (Error error, + bool outQueueChanged, + uint32_t outLength, + vec outHandles); }; diff --git a/graphics/composer/2.3/utils/command-buffer/Android.bp b/graphics/composer/2.3/utils/command-buffer/Android.bp new file mode 100644 index 0000000000..c48fe7a53c --- /dev/null +++ b/graphics/composer/2.3/utils/command-buffer/Android.bp @@ -0,0 +1,15 @@ +cc_library_headers { + name: "android.hardware.graphics.composer@2.3-command-buffer", + defaults: ["hidl_defaults"], + vendor_available: true, + shared_libs: [ + "android.hardware.graphics.composer@2.1", + "android.hardware.graphics.composer@2.2", + "android.hardware.graphics.composer@2.3", + ], + header_libs: [ + "android.hardware.graphics.composer@2.1-command-buffer", + "android.hardware.graphics.composer@2.2-command-buffer", + ], + export_include_dirs: ["include"], +} diff --git a/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h b/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h new file mode 100644 index 0000000000..3f7b2c95f0 --- /dev/null +++ b/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h @@ -0,0 +1,76 @@ +/* + * 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 +#warn "ComposerCommandBuffer.h included without LOG_TAG" +#endif + +#undef LOG_NDEBUG +#define LOG_NDEBUG 0 + +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_3 { + +using android::hardware::MessageQueue; +using android::hardware::graphics::composer::V2_1::Error; +using android::hardware::graphics::composer::V2_1::IComposerCallback; +using android::hardware::graphics::composer::V2_1::Layer; +using android::hardware::graphics::composer::V2_3::IComposerClient; + +// This class helps build a command queue. Note that all sizes/lengths are in +// units of uint32_t's. +class CommandWriterBase : public V2_2::CommandWriterBase { + public: + CommandWriterBase(uint32_t initialMaxSize) : V2_2::CommandWriterBase(initialMaxSize) {} + + static constexpr uint16_t kSetLayerColorTransformLength = 16; + void setLayerColorTransform(const float* matrix) { + beginCommand_2_3(IComposerClient::Command::SET_LAYER_COLOR_TRANSFORM, + kSetLayerColorTransformLength); + for (int i = 0; i < 16; i++) { + writeFloat(matrix[i]); + } + endCommand(); + } + + protected: + void beginCommand_2_3(IComposerClient::Command command, uint16_t length) { + V2_2::CommandWriterBase::beginCommand_2_2( + static_cast(static_cast(command)), length); + } +}; + +// This class helps parse a command queue. Note that all sizes/lengths are in +// units of uint32_t's. +class CommandReaderBase : public V2_2::CommandReaderBase { + public: + CommandReaderBase() : V2_2::CommandReaderBase(){}; +}; + +} // namespace V2_3 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/graphics/composer/2.3/utils/hal/Android.bp b/graphics/composer/2.3/utils/hal/Android.bp index aa46df1ebb..3ee930050c 100644 --- a/graphics/composer/2.3/utils/hal/Android.bp +++ b/graphics/composer/2.3/utils/hal/Android.bp @@ -26,9 +26,11 @@ cc_library_headers { ], header_libs: [ "android.hardware.graphics.composer@2.2-hal", + "android.hardware.graphics.composer@2.3-command-buffer", ], export_header_lib_headers: [ "android.hardware.graphics.composer@2.2-hal", + "android.hardware.graphics.composer@2.3-command-buffer", ], export_include_dirs: ["include"], } diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h index e717d84ba8..c805472e9e 100644 --- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h +++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h @@ -22,6 +22,7 @@ #include #include +#include #include namespace android { @@ -55,10 +56,27 @@ class ComposerClientImpl : public V2_2::hal::detail::ComposerClientImpl executeCommands_2_3(uint32_t inLength, const hidl_vec& inHandles, + IComposerClient::executeCommands_2_2_cb hidl_cb) override { + std::lock_guard lock(mCommandEngineMutex); + bool outChanged = false; + uint32_t outLength = 0; + hidl_vec outHandles; + Error error = + mCommandEngine->execute(inLength, inHandles, &outChanged, &outLength, &outHandles); + + hidl_cb(error, outChanged, outLength, outHandles); + + mCommandEngine->reset(); + + return Void(); + } + private: using BaseType2_2 = V2_2::hal::detail::ComposerClientImpl; using BaseType2_1 = V2_1::hal::detail::ComposerClientImpl; - + using BaseType2_1::mCommandEngine; + using BaseType2_1::mCommandEngineMutex; using BaseType2_1::mHal; }; diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerCommandEngine.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerCommandEngine.h new file mode 100644 index 0000000000..c3dcbcd4a6 --- /dev/null +++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerCommandEngine.h @@ -0,0 +1,81 @@ +/* + * 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 +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_3 { +namespace hal { + +class ComposerCommandEngine : public V2_2::hal::ComposerCommandEngine { + public: + ComposerCommandEngine(ComposerHal* hal, V2_2::hal::ComposerResources* resources) + : BaseType2_2(hal, resources), mHal(hal) {} + + protected: + bool executeCommand(V2_1::IComposerClient::Command command, uint16_t length) override { + switch (static_cast(command)) { + case IComposerClient::Command::SET_LAYER_COLOR_TRANSFORM: + return executeSetLayerColorTransform(length); + default: + return BaseType2_2::executeCommand(command, length); + } + } + + bool executeSetLayerColorTransform(uint16_t length) { + if (length != CommandWriterBase::kSetLayerColorTransformLength) { + return false; + } + + float matrix[16]; + for (int i = 0; i < 16; i++) { + matrix[i] = readFloat(); + } + auto err = mHal->setLayerColorTransform(mCurrentDisplay, mCurrentLayer, matrix); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; + } + + private: + using BaseType2_1 = V2_1::hal::ComposerCommandEngine; + using BaseType2_1::mWriter; + using BaseType2_2 = V2_2::hal::ComposerCommandEngine; + + ComposerHal* mHal; +}; + +} // namespace hal +} // namespace V2_3 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h index 37ea0a3c46..0f6205abb7 100644 --- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h +++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h @@ -27,11 +27,13 @@ namespace hal { using V2_1::Display; using V2_1::Error; +using V2_1::Layer; class ComposerHal : public V2_2::hal::ComposerHal { public: virtual Error getDisplayIdentificationData(Display display, uint8_t* outPort, std::vector* outData) = 0; + virtual Error setLayerColorTransform(Display display, Layer layer, const float* matrix) = 0; }; } // namespace hal diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h index 53f2d1b254..ed1878b583 100644 --- a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h +++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h @@ -66,6 +66,14 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { return Error::NONE; } + Error setLayerColorTransform(Display display, Layer layer, const float* matrix) override { + if (!mDispatch.setLayerColorTransform) { + return Error::UNSUPPORTED; + } + int32_t err = mDispatch.setLayerColorTransform(mDevice, display, layer, matrix); + return static_cast(err); + } + protected: bool initDispatch() override { if (!BaseType2_2::initDispatch()) { @@ -74,12 +82,15 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl { this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_IDENTIFICATION_DATA, &mDispatch.getDisplayIdentificationData); + this->initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_COLOR_TRANSFORM, + &mDispatch.setLayerColorTransform); return true; } private: struct { HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA getDisplayIdentificationData; + HWC2_PFN_SET_LAYER_COLOR_TRANSFORM setLayerColorTransform; } mDispatch = {}; using BaseType2_2 = V2_2::passthrough::detail::HwcHalImpl; diff --git a/graphics/composer/2.3/utils/vts/Android.bp b/graphics/composer/2.3/utils/vts/Android.bp index 05532586ef..19438cbe26 100644 --- a/graphics/composer/2.3/utils/vts/Android.bp +++ b/graphics/composer/2.3/utils/vts/Android.bp @@ -31,6 +31,7 @@ cc_library_static { header_libs: [ "android.hardware.graphics.composer@2.1-command-buffer", "android.hardware.graphics.composer@2.2-command-buffer", + "android.hardware.graphics.composer@2.3-command-buffer", ], cflags: [ "-O0", diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp index df696c9273..7548cb521e 100644 --- a/graphics/composer/2.3/vts/functional/Android.bp +++ b/graphics/composer/2.3/vts/functional/Android.bp @@ -40,5 +40,6 @@ cc_test { header_libs: [ "android.hardware.graphics.composer@2.1-command-buffer", "android.hardware.graphics.composer@2.2-command-buffer", + "android.hardware.graphics.composer@2.3-command-buffer", ], } diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp index f4e34f08ff..1030ddc9db 100644 --- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp +++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp @@ -20,7 +20,9 @@ #include #include +#include #include +#include #include namespace android { @@ -65,6 +67,9 @@ class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { // explicitly disable vsync mComposerClient->setVsyncEnabled(mPrimaryDisplay, false); mComposerCallback->setVsyncAllowed(false); + + mWriter = std::make_unique(1024); + mReader = std::make_unique(); } void TearDown() override { @@ -75,11 +80,18 @@ class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { } } + void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); } + + // use the slot count usually set by SF + static constexpr uint32_t kBufferSlotCount = 64; + std::unique_ptr mComposer; std::unique_ptr mComposerClient; sp mComposerCallback; // the first display and is assumed never to be removed Display mPrimaryDisplay; + std::unique_ptr mWriter; + std::unique_ptr mReader; private: Display waitForFirstDisplay() { @@ -115,6 +127,31 @@ TEST_F(GraphicsComposerHidlTest, GetDisplayIdentificationData) { } } +/** + * Test IComposerClient::Command::SET_LAYER_COLOR_TRANSFORM. + * TODO Add color to the layer, use matrix to keep only red component, + * and check. + */ +TEST_F(GraphicsComposerHidlTest, SetLayerColorTransform) { + Layer layer; + ASSERT_NO_FATAL_FAILURE(layer = + mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); + mWriter->selectDisplay(mPrimaryDisplay); + mWriter->selectLayer(layer); + + // clang-format off + const std::array matrix = {{ + 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, + }}; + // clang-format on + + mWriter->setLayerColorTransform(matrix.data()); + execute(); +} + } // namespace } // namespace vts } // namespace V2_3