mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 16:50:18 +00:00
[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
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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<uint8_t> 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<handle> inHandles)
|
||||
generates (Error error,
|
||||
bool outQueueChanged,
|
||||
uint32_t outLength,
|
||||
vec<handle> outHandles);
|
||||
};
|
||||
|
||||
15
graphics/composer/2.3/utils/command-buffer/Android.bp
Normal file
15
graphics/composer/2.3/utils/command-buffer/Android.bp
Normal file
@@ -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"],
|
||||
}
|
||||
@@ -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 <android/hardware/graphics/composer/2.3/IComposer.h>
|
||||
#include <android/hardware/graphics/composer/2.3/IComposerClient.h>
|
||||
#include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
|
||||
|
||||
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<V2_2::IComposerClient::Command>(static_cast<int32_t>(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
|
||||
@@ -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"],
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <android/hardware/graphics/composer/2.3/IComposerClient.h>
|
||||
#include <composer-hal/2.3/ComposerClient.h>
|
||||
#include <composer-hal/2.3/ComposerCommandEngine.h>
|
||||
#include <composer-hal/2.3/ComposerHal.h>
|
||||
|
||||
namespace android {
|
||||
@@ -55,10 +56,27 @@ class ComposerClientImpl : public V2_2::hal::detail::ComposerClientImpl<Interfac
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> executeCommands_2_3(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles,
|
||||
IComposerClient::executeCommands_2_2_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();
|
||||
}
|
||||
|
||||
private:
|
||||
using BaseType2_2 = V2_2::hal::detail::ComposerClientImpl<Interface, Hal>;
|
||||
using BaseType2_1 = V2_1::hal::detail::ComposerClientImpl<Interface, Hal>;
|
||||
|
||||
using BaseType2_1::mCommandEngine;
|
||||
using BaseType2_1::mCommandEngineMutex;
|
||||
using BaseType2_1::mHal;
|
||||
};
|
||||
|
||||
|
||||
@@ -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 <composer-command-buffer/2.3/ComposerCommandBuffer.h>
|
||||
#include <composer-hal/2.1/ComposerCommandEngine.h>
|
||||
#include <composer-hal/2.2/ComposerCommandEngine.h>
|
||||
#include <composer-hal/2.2/ComposerResources.h>
|
||||
#include <composer-hal/2.3/ComposerHal.h>
|
||||
|
||||
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<IComposerClient::Command>(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
|
||||
@@ -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<uint8_t>* outData) = 0;
|
||||
virtual Error setLayerColorTransform(Display display, Layer layer, const float* matrix) = 0;
|
||||
};
|
||||
|
||||
} // namespace hal
|
||||
|
||||
@@ -66,6 +66,14 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl<Hal> {
|
||||
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<Error>(err);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool initDispatch() override {
|
||||
if (!BaseType2_2::initDispatch()) {
|
||||
@@ -74,12 +82,15 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl<Hal> {
|
||||
|
||||
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<Hal>;
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -20,7 +20,9 @@
|
||||
|
||||
#include <VtsHalHidlTargetTestBase.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <composer-command-buffer/2.3/ComposerCommandBuffer.h>
|
||||
#include <composer-vts/2.1/GraphicsComposerCallback.h>
|
||||
#include <composer-vts/2.1/TestCommandReader.h>
|
||||
#include <composer-vts/2.3/ComposerVts.h>
|
||||
|
||||
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<CommandWriterBase>(1024);
|
||||
mReader = std::make_unique<V2_1::vts::TestCommandReader>();
|
||||
}
|
||||
|
||||
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<Composer> mComposer;
|
||||
std::unique_ptr<ComposerClient> mComposerClient;
|
||||
sp<V2_1::vts::GraphicsComposerCallback> mComposerCallback;
|
||||
// the first display and is assumed never to be removed
|
||||
Display mPrimaryDisplay;
|
||||
std::unique_ptr<CommandWriterBase> mWriter;
|
||||
std::unique_ptr<V2_1::vts::TestCommandReader> 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<float, 16> 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
|
||||
|
||||
Reference in New Issue
Block a user