diff --git a/current.txt b/current.txt index 06c94d93f8..655fb13087 100644 --- a/current.txt +++ b/current.txt @@ -323,9 +323,9 @@ be794f5df97f134d6dcabb866b250d1305100e7ae07fb253b7841df890b931bb android.hardwar 3c5183d7506010be57e0f748e3640fc2ded1ba955784b6256ba427f4c399591c android.hardware.gnss@1.1::IGnssConfiguration b054af24fbb70d54cde1fb5cba126809e7c4e863e8f9115dc492321dfbcbc993 android.hardware.gnss@1.1::IGnssMeasurement 83e7a10ff3702147bd7ffa04567b20d407a3b16bbb7705644af44d919afe9103 android.hardware.gnss@1.1::IGnssMeasurementCallback -82da7e7624f72ff1927f48738913e20bee3a513adfe5dc7c4f888176e20376e6 android.hardware.graphics.common@1.1::types +0b96e0254e2168cfecb30c1ed5fb42681652cc00faa68c6e07568fafe64d1d50 android.hardware.graphics.common@1.1::types d9b40a5b09962a5a0780b10fe33a4e607e69e2e088fc83de88a584115b7cb1c0 android.hardware.graphics.composer@2.2::IComposer -d6ce042995239712bc1d0970fa9d512c15c0b1ac9bcb048bd8b69f617b45c25e android.hardware.graphics.composer@2.2::IComposerClient +da3979dd97093cdc4ffc2e2427e848f4ba07ddcd181f31f2cb494ad0d2fa58ad android.hardware.graphics.composer@2.2::IComposerClient dd83be076b6b3f10ed62ab34d8c8b95f2415961fb785200eb842e7bfb2b0ee92 android.hardware.graphics.mapper@2.1::IMapper 675682dd3007805c985eaaec91612abc88f4c25b3431fb84070b7584a1a741fb android.hardware.health@2.0::IHealth 434c4c32c00b0e54bb05e40c79503208b40f786a318029a2a4f66e34f10f2a76 android.hardware.health@2.0::IHealthInfoCallback diff --git a/graphics/common/1.1/Android.bp b/graphics/common/1.1/Android.bp index c319d80030..8bc68f545d 100644 --- a/graphics/common/1.1/Android.bp +++ b/graphics/common/1.1/Android.bp @@ -15,8 +15,10 @@ hidl_interface { ], types: [ "BufferUsage", + "ColorMode", "Dataspace", "PixelFormat", + "RenderIntent", ], gen_java: true, gen_java_constants: true, diff --git a/graphics/common/1.1/types.hal b/graphics/common/1.1/types.hal index b917d5e851..5dca4829f0 100644 --- a/graphics/common/1.1/types.hal +++ b/graphics/common/1.1/types.hal @@ -16,9 +16,10 @@ package android.hardware.graphics.common@1.1; -import @1.0::PixelFormat; import @1.0::BufferUsage; +import @1.0::ColorMode; import @1.0::Dataspace; +import @1.0::PixelFormat; /** * Pixel formats for graphics buffers. @@ -129,15 +130,165 @@ enum BufferUsage : @1.0::BufferUsage { @export(name="android_dataspace_v1_1_t", value_prefix="HAL_DATASPACE_", export_parent="false") enum Dataspace : @1.0::Dataspace { + /* + * @1.0::Dataspace defines six legacy dataspaces + * + * SRGB_LINEAR = 0x200, // deprecated, use V0_SRGB_LINEAR + * SRGB = 0x201, // deprecated, use V0_SRGB + * JFIF = 0x101, // deprecated, use V0_JFIF + * BT601_625 = 0x102, // deprecated, use V0_BT601_625 + * BT601_525 = 0x103, // deprecated, use V0_BT601_525 + * BT709 = 0x104, // deprecated, use V0_BT709 + * + * The difference between the legacy dataspaces and their modern + * counterparts is that, with legacy dataspaces, the pixel values may have + * been desaturated by the content creator in an unspecified way. + * + * When colorimetric mapping is required, the legacy dataspaces must be + * treated as their modern counterparts (e.g., SRGB must be treated as + * V0_SRGB) and no re-saturation is allowed. When non-colorimetric mapping + * is allowed, the pixel values can be interpreted freely by + * implementations for the purpose of re-saturation, and the re-saturated + * pixel values are in the respective modern dataspaces. + * + * This is also true when UNKNOWN is treated as a legacy dataspace. + */ + /** * ITU-R Recommendation 2020 (BT.2020) * * Ultra High-definition television * - * Use limited range, SMPTE 2084 (PQ) transfer and BT2020 standard - * limited range is the preferred / normative definition for BT.2020 + * Use limited range, BT.709 transfer and BT2020 standard */ BT2020_ITU = STANDARD_BT2020 | TRANSFER_SMPTE_170M | RANGE_LIMITED, + /** + * ITU-R Recommendation 2100 (BT.2100) + * + * High dynamic range television + * + * Use limited/full range, PQ/HLG transfer, and BT2020 standard + * limited range is the preferred / normative definition for BT.2100 + */ BT2020_ITU_PQ = STANDARD_BT2020 | TRANSFER_ST2084 | RANGE_LIMITED, + BT2020_ITU_HLG = STANDARD_BT2020 | TRANSFER_HLG | RANGE_LIMITED, + BT2020_HLG = STANDARD_BT2020 | TRANSFER_HLG | RANGE_FULL, +}; + +@export(name="android_color_mode_v1_1_t", value_prefix="HAL_COLOR_MODE_", + export_parent="false") +enum ColorMode : @1.0::ColorMode { + /** + * BT2020 corresponds with display settings that implement the ITU-R + * Recommendation BT.2020 / Rec. 2020 for UHDTV. + * + * Primaries: + * x y + * green 0.170 0.797 + * blue 0.131 0.046 + * red 0.708 0.292 + * white (D65) 0.3127 0.3290 + * + * Inverse Gamma Correction (IGC): V represents normalized (with [0 to 1] + * range) value of R, G, or B. + * + * if Vnonlinear < b * 4.5 + * Vlinear = Vnonlinear / 4.5 + * else + * Vlinear = ((Vnonlinear + (a - 1)) / a) ^ (1/0.45) + * + * Gamma Correction (GC): + * + * if Vlinear < b + * Vnonlinear = 4.5 * Vlinear + * else + * Vnonlinear = a * Vlinear ^ 0.45 - (a - 1) + * + * where + * + * a = 1.09929682680944, b = 0.018053968510807 + * + * For practical purposes, these a/b values can be used instead + * + * a = 1.099, b = 0.018 for 10-bit display systems + * a = 1.0993, b = 0.0181 for 12-bit display systems + */ + BT2020 = 10, + + /** + * BT2100_PQ and BT2100_HLG correspond with display settings that + * implement the ITU-R Recommendation BT.2100 / Rec. 2100 for HDR TV. + * + * Primaries: + * x y + * green 0.170 0.797 + * blue 0.131 0.046 + * red 0.708 0.292 + * white (D65) 0.3127 0.3290 + * + * For BT2100_PQ, the transfer function is Perceptual Quantizer (PQ). For + * BT2100_HLG, the transfer function is Hybrid Log-Gamma (HLG). + */ + BT2100_PQ = 11, + BT2100_HLG = 12, +}; + +/** + * RenderIntent defines the mapping from color mode colors to display colors. + * + * A render intent must not change how it maps colors when the color mode + * changes. That is to say that when a render intent maps color C to color C', + * the fact that color C can have different pixel values in different color + * modes should not affect the mapping. + * + * RenderIntent overrides the render intents defined for individual color + * modes. It is ignored when the color mode is ColorMode::NATIVE, because + * ColorMode::NATIVE colors are already display colors. + */ +@export(name="android_render_intent_v1_1_t", value_prefix="HAL_RENDER_INTENT_", + export_parent="false") +enum RenderIntent : int32_t { + /** + * Colors in the display gamut are unchanged. Colors out of the display + * gamut are hard-clipped. + * + * This implies that the display must have been calibrated unless + * ColorMode::NATIVE is the only supported color mode. + */ + COLORIMETRIC = 0, + + /** + * Enhance colors that are in the display gamut. Colors out of the display + * gamut are hard-clipped. + * + * The enhancement typically picks the biggest standard color space (e.g. + * DCI-P3) that is narrower than the display gamut and stretches it to the + * display gamut. The stretching is recommended to preserve skin tones. + */ + ENHANCE = 1, + + /** + * Tone map high-dynamic-range colors to the display's dynamic range. The + * dynamic range of the colors are communicated separately. After tone + * mapping, the mapping to the display gamut is as defined in + * COLORIMETRIC. + */ + TONE_MAP_COLORIMETRIC = 2, + + /** + * Tone map high-dynamic-range colors to the display's dynamic range. The + * dynamic range of the colors are communicated separately. After tone + * mapping, the mapping to the display gamut is as defined in ENHANCE. + * + * The tone mapping step and the enhancing step must match + * TONE_MAP_COLORIMETRIC and ENHANCE respectively when they are also + * supported. + */ + TONE_MAP_ENHANCE = 3, + + /* + * Vendors are recommended to use 0x100 - 0x1FF for their own values, and + * that must be done with subtypes defined by vendor extensions. + */ }; diff --git a/graphics/composer/2.2/Android.bp b/graphics/composer/2.2/Android.bp index 633a208cf1..fe71e9ec71 100644 --- a/graphics/composer/2.2/Android.bp +++ b/graphics/composer/2.2/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.hidl.base@1.0", ], diff --git a/graphics/composer/2.2/IComposerClient.hal b/graphics/composer/2.2/IComposerClient.hal index dcd9c8d04a..657bcac8e0 100644 --- a/graphics/composer/2.2/IComposerClient.hal +++ b/graphics/composer/2.2/IComposerClient.hal @@ -16,8 +16,10 @@ package android.hardware.graphics.composer@2.2; -import android.hardware.graphics.common@1.0::PixelFormat; import android.hardware.graphics.common@1.0::Dataspace; +import android.hardware.graphics.common@1.0::PixelFormat; +import android.hardware.graphics.common@1.1::ColorMode; +import android.hardware.graphics.common@1.1::RenderIntent; import @2.1::IComposerClient; import @2.1::Display; import @2.1::Error; @@ -90,16 +92,20 @@ interface IComposerClient extends @2.1::IComposerClient { enum Command : @2.1::IComposerClient.Command { /** - * setPerFrameMetadata(Display display, vec data) + * SET_LAYER_PER_FRAME_METADATA has this pseudo prototype + * + * setLayerPerFrameMetadata(Display display, Layer layer, + * vec data); + * * Sets the PerFrameMetadata for the display. This metadata must be used * by the implementation to better tone map content to that display. * * This is a method that may be called every frame. Thus it's * implemented using buffered transport. - * SET_PER_FRAME_METADATA is the command used by the buffered transport + * SET_LAYER_PER_FRAME_METADATA is the command used by the buffered transport * mechanism. */ - SET_PER_FRAME_METADATA = 0x207 << @2.1::IComposerClient.Command:OPCODE_SHIFT, + SET_LAYER_PER_FRAME_METADATA = 0x303 << @2.1::IComposerClient.Command:OPCODE_SHIFT, /** * SET_LAYER_COLOR has this pseudo prototype @@ -260,4 +266,118 @@ interface IComposerClient extends @2.1::IComposerClient { */ setPowerMode_2_2(Display display, PowerMode mode) generates (Error error); + /** + * Returns the color modes supported on this display. + * + * All devices must support at least ColorMode::NATIVE. + * + * @param display is the display to query. + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * @return modes is an array of color modes. + */ + getColorModes_2_2(Display display) + generates (Error error, + vec modes); + + /** + * Returns the render intents supported by the specified display and color + * mode. + * + * RenderIntent::COLORIMETRIC is always supported. + * + * @param display is the display to query. + * @param mode is the color mode to query. + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * BAD_PARAMETER when an invalid color mode was passed in. + * @return intents is an array of render intents. + */ + getRenderIntents(Display display, ColorMode mode) + generates (Error error, + vec intents); + + /** + * Sets the color mode and render intent of the given display. + * + * The color mode and render intent change must take effect on next + * presentDisplay. + * + * All devices must support at least ColorMode::NATIVE and + * RenderIntent::COLORIMETRIC, and displays are assumed to be in this mode + * upon hotplug. + * + * @param display is the display to which the color mode is set. + * @param mode is the color mode to set to. + * @param intent is the render intent to set to. + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * BAD_PARAMETER when mode or intent is invalid + * UNSUPPORTED when mode or intent is not supported on this + * display. + */ + setColorMode_2_2(Display display, ColorMode mode, RenderIntent intent) + generates (Error error); + + /* + * By default, layer dataspaces are mapped to the current color mode + * colorimetrically with a few exceptions. + * + * When the layer dataspace is a legacy sRGB dataspace + * (Dataspace::SRGB_LINEAR, Dataspace::SRGB, or Dataspace::UNKNOWN when + * treated as such) and the display render intent is + * RenderIntent::ENHANCE, the pixel values can go through an + * implementation-defined saturation transform before being mapped to the + * current color mode colorimetrically. + * + * Colors that are out of the gamut of the current color mode are + * hard-clipped. + */ + + /** + * Returns the saturation matrix of the specified legacy dataspace. + * + * The saturation matrix can be used to approximate the legacy dataspace + * saturation transform. It is to be applied on linear pixel values like + * this: + * + * (in GLSL) + * linearSrgb = clamp(saturationMatrix * linearSrgb, 0.0, 1.0); + * + * @param dataspace must be Dataspace::SRGB_LINEAR. + * @return error is NONE upon success. Otherwise, + * BAD_PARAMETER when an invalid dataspace was passed in. + * @return matrix is the 4x4 column-major matrix used to approximate the + * legacy dataspace saturation operation. The last row must be + * [0.0, 0.0, 0.0, 1.0]. + */ + getDataspaceSaturationMatrix(Dataspace dataspace) + generates (Error error, + float[4][4] matrix); + + /** + * 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_2(uint32_t inLength, + vec inHandles) + generates (Error error, + bool outQueueChanged, + uint32_t outLength, + vec outHandles); }; diff --git a/graphics/composer/2.2/default/Android.bp b/graphics/composer/2.2/default/Android.bp deleted file mode 100644 index 906479e6ac..0000000000 --- a/graphics/composer/2.2/default/Android.bp +++ /dev/null @@ -1,31 +0,0 @@ -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/Android.mk b/graphics/composer/2.2/default/Android.mk new file mode 100644 index 0000000000..2f80f0c19e --- /dev/null +++ b/graphics/composer/2.2/default/Android.mk @@ -0,0 +1,32 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := android.hardware.graphics.composer@2.2-service +LOCAL_VENDOR_MODULE := true +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_CFLAGS := -Wall -Werror -DLOG_TAG=\"ComposerHal\" +LOCAL_SRC_FILES := service.cpp +LOCAL_INIT_RC := android.hardware.graphics.composer@2.2-service.rc +LOCAL_HEADER_LIBRARIES := android.hardware.graphics.composer@2.2-passthrough +LOCAL_SHARED_LIBRARIES := \ + 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 + +ifdef TARGET_USES_DISPLAY_RENDER_INTENTS +LOCAL_CFLAGS += -DUSES_DISPLAY_RENDER_INTENTS +endif + +include $(BUILD_EXECUTABLE) diff --git a/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h b/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h index c803d3ca97..b499ca9754 100644 --- a/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h +++ b/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h @@ -72,8 +72,9 @@ class CommandWriterBase : public V2_1::CommandWriterBase { endCommand(); } - void setPerFrameMetadata(const hidl_vec& metadataVec) { - beginCommand_2_2(IComposerClient::Command::SET_PER_FRAME_METADATA, metadataVec.size() * 2); + void setLayerPerFrameMetadata(const hidl_vec& metadataVec) { + beginCommand_2_2(IComposerClient::Command::SET_LAYER_PER_FRAME_METADATA, + metadataVec.size() * 2); for (const auto& metadata : metadataVec) { writeSigned(static_cast(metadata.key)); writeFloat(metadata.value); 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 index d550f834b9..ba6723de52 100644 --- 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 @@ -103,6 +103,64 @@ class ComposerClientImpl : public V2_1::hal::detail::ComposerClientImplsetPowerMode_2_2(display, mode); } + Return getColorModes_2_2(Display display, + IComposerClient::getColorModes_2_2_cb hidl_cb) override { + hidl_vec modes; + Error err = mHal->getColorModes_2_2(display, &modes); + hidl_cb(err, modes); + return Void(); + } + + Return getRenderIntents(Display display, ColorMode mode, + IComposerClient::getRenderIntents_cb hidl_cb) override { +#ifdef USES_DISPLAY_RENDER_INTENTS + std::vector intents; + Error err = mHal->getRenderIntents(display, mode, &intents); + hidl_cb(err, intents); +#else + (void)display; + (void)mode; + hidl_cb(Error::NONE, hidl_vec({RenderIntent::COLORIMETRIC})); +#endif + return Void(); + } + + Return setColorMode_2_2(Display display, ColorMode mode, RenderIntent intent) override { +#ifndef USES_DISPLAY_RENDER_INTENTS + if (intent != RenderIntent::COLORIMETRIC) { + return Error::BAD_PARAMETER; + } +#endif + return mHal->setColorMode_2_2(display, mode, intent); + } + + Return getDataspaceSaturationMatrix( + Dataspace dataspace, IComposerClient::getDataspaceSaturationMatrix_cb hidl_cb) override { + if (dataspace != Dataspace::SRGB_LINEAR) { + hidl_cb(Error::BAD_PARAMETER, std::array{0.0f}.data()); + return Void(); + } + + hidl_cb(Error::NONE, mHal->getDataspaceSaturationMatrix(dataspace).data()); + return Void(); + } + + Return executeCommands_2_2(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(); + } + protected: std::unique_ptr createResources() override { return ComposerResources::create(); @@ -146,6 +204,8 @@ class ComposerClientImpl : public V2_1::hal::detail::ComposerClientImpl; + using BaseType2_1::mCommandEngine; + using BaseType2_1::mCommandEngineMutex; using BaseType2_1::mHal; using BaseType2_1::mResources; }; 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 index adcac463d9..97e3a9ece6 100644 --- 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 @@ -40,8 +40,8 @@ class ComposerCommandEngine : public V2_1::hal::ComposerCommandEngine { protected: bool executeCommand(V2_1::IComposerClient::Command command, uint16_t length) override { switch (static_cast(command)) { - case IComposerClient::Command::SET_PER_FRAME_METADATA: - return executeSetPerFrameMetadata(length); + case IComposerClient::Command::SET_LAYER_PER_FRAME_METADATA: + return executeSetLayerPerFrameMetadata(length); case IComposerClient::Command::SET_LAYER_FLOAT_COLOR: return executeSetLayerFloatColor(length); default: @@ -49,7 +49,7 @@ class ComposerCommandEngine : public V2_1::hal::ComposerCommandEngine { } } - bool executeSetPerFrameMetadata(uint16_t length) { + bool executeSetLayerPerFrameMetadata(uint16_t length) { // (key, value) pairs if (length % 2 != 0) { return false; @@ -63,7 +63,7 @@ class ComposerCommandEngine : public V2_1::hal::ComposerCommandEngine { length -= 2; } - auto err = mHal->setPerFrameMetadata(mCurrentDisplay, metadata); + auto err = mHal->setLayerPerFrameMetadata(mCurrentDisplay, mCurrentLayer, metadata); if (err != Error::NONE) { mWriter.setError(getCommandLoc(), err); } 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 index 30b364398a..12191bee57 100644 --- 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 @@ -30,6 +30,8 @@ namespace hal { using common::V1_0::Dataspace; using common::V1_0::PixelFormat; +using common::V1_1::ColorMode; +using common::V1_1::RenderIntent; using V2_1::Display; using V2_1::Error; using V2_1::Layer; @@ -41,10 +43,21 @@ class ComposerHal : public V2_1::hal::ComposerHal { return setPowerMode_2_2(display, static_cast(mode)); } + // superceded by getColorModes_2_2 + Error getColorModes(Display display, hidl_vec* outModes) override { + return getColorModes_2_2(display, reinterpret_cast*>(outModes)); + } + + // superceded by setColorMode_2_2 + Error setColorMode(Display display, common::V1_0::ColorMode mode) override { + return setColorMode_2_2(display, static_cast(mode), RenderIntent::COLORIMETRIC); + } + virtual Error getPerFrameMetadataKeys( Display display, std::vector* outKeys) = 0; - virtual Error setPerFrameMetadata( - Display display, const std::vector& metadata) = 0; + virtual Error setLayerPerFrameMetadata( + Display display, Layer layer, + const std::vector& metadata) = 0; virtual Error getReadbackBufferAttributes(Display display, PixelFormat* outFormat, Dataspace* outDataspace) = 0; @@ -56,6 +69,13 @@ class ComposerHal : public V2_1::hal::ComposerHal { virtual Error setLayerFloatColor(Display display, Layer layer, IComposerClient::FloatColor color) = 0; + + virtual Error getColorModes_2_2(Display display, hidl_vec* outModes) = 0; + virtual Error getRenderIntents(Display display, ColorMode mode, + std::vector* outIntents) = 0; + virtual Error setColorMode_2_2(Display display, ColorMode mode, RenderIntent intent) = 0; + + virtual std::array getDataspaceSaturationMatrix(Dataspace dataspace) = 0; }; } // namespace hal 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 index b251351f15..7e38a7973e 100644 --- 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 @@ -36,6 +36,8 @@ namespace detail { using common::V1_0::Dataspace; using common::V1_0::PixelFormat; +using common::V1_1::ColorMode; +using common::V1_1::RenderIntent; using V2_1::Display; using V2_1::Error; using V2_1::Layer; @@ -72,9 +74,10 @@ class HwcHalImpl : public V2_1::passthrough::detail::HwcHalImpl { return Error::NONE; } - Error setPerFrameMetadata( - Display display, const std::vector& metadata) override { - if (!mDispatch.setPerFrameMetadata) { + Error setLayerPerFrameMetadata( + Display display, Layer layer, + const std::vector& metadata) override { + if (!mDispatch.setLayerPerFrameMetadata) { return Error::UNSUPPORTED; } @@ -87,8 +90,8 @@ class HwcHalImpl : public V2_1::passthrough::detail::HwcHalImpl { values.push_back(m.value); } - int32_t error = mDispatch.setPerFrameMetadata(mDevice, display, metadata.size(), - keys.data(), values.data()); + int32_t error = mDispatch.setLayerPerFrameMetadata(mDevice, display, layer, metadata.size(), + keys.data(), values.data()); return static_cast(error); } @@ -149,6 +152,69 @@ class HwcHalImpl : public V2_1::passthrough::detail::HwcHalImpl { return static_cast(error); } + Error getColorModes_2_2(Display display, hidl_vec* outModes) override { + return getColorModes(display, + reinterpret_cast*>(outModes)); + } + + Error getRenderIntents(Display display, ColorMode mode, + std::vector* outIntents) override { + if (!mDispatch.getRenderIntents) { + *outIntents = std::vector({RenderIntent::COLORIMETRIC}); + return Error::NONE; + } + + uint32_t count = 0; + int32_t error = + mDispatch.getRenderIntents(mDevice, display, int32_t(mode), &count, nullptr); + if (error != HWC2_ERROR_NONE) { + return static_cast(error); + } + + std::vector intents(count); + error = mDispatch.getRenderIntents( + mDevice, display, int32_t(mode), &count, + reinterpret_cast::type*>(intents.data())); + if (error != HWC2_ERROR_NONE) { + return static_cast(error); + } + intents.resize(count); + + *outIntents = std::move(intents); + return Error::NONE; + } + + Error setColorMode_2_2(Display display, ColorMode mode, RenderIntent intent) override { + if (!mDispatch.setColorModeWithRenderIntent) { + if (intent != RenderIntent::COLORIMETRIC) { + return Error::UNSUPPORTED; + } + return setColorMode(display, static_cast(mode)); + } + + int32_t err = mDispatch.setColorModeWithRenderIntent( + mDevice, display, static_cast(mode), static_cast(intent)); + return static_cast(err); + } + + std::array getDataspaceSaturationMatrix(Dataspace dataspace) override { + std::array matrix; + + int32_t error = HWC2_ERROR_UNSUPPORTED; + if (mDispatch.getDataspaceSaturationMatrix) { + error = mDispatch.getDataspaceSaturationMatrix(mDevice, static_cast(dataspace), + matrix.data()); + } + if (error != HWC2_ERROR_NONE) { + return std::array{ + 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, + }; + } + + return matrix; + } + protected: template bool initOptionalDispatch(hwc2_function_descriptor_t desc, T* outPfn) { @@ -168,7 +234,8 @@ class HwcHalImpl : public V2_1::passthrough::detail::HwcHalImpl { initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_FLOAT_COLOR, &mDispatch.setLayerFloatColor); - initOptionalDispatch(HWC2_FUNCTION_SET_PER_FRAME_METADATA, &mDispatch.setPerFrameMetadata); + initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_PER_FRAME_METADATA, + &mDispatch.setLayerPerFrameMetadata); initOptionalDispatch(HWC2_FUNCTION_GET_PER_FRAME_METADATA_KEYS, &mDispatch.getPerFrameMetadataKeys); @@ -178,21 +245,32 @@ class HwcHalImpl : public V2_1::passthrough::detail::HwcHalImpl { initOptionalDispatch(HWC2_FUNCTION_GET_READBACK_BUFFER_FENCE, &mDispatch.getReadbackBufferFence); + initOptionalDispatch(HWC2_FUNCTION_GET_RENDER_INTENTS, &mDispatch.getRenderIntents); + initOptionalDispatch(HWC2_FUNCTION_SET_COLOR_MODE_WITH_RENDER_INTENT, + &mDispatch.setColorModeWithRenderIntent); + initOptionalDispatch(HWC2_FUNCTION_GET_DATASPACE_SATURATION_MATRIX, + &mDispatch.getDataspaceSaturationMatrix); + return true; } struct { HWC2_PFN_SET_LAYER_FLOAT_COLOR setLayerFloatColor; - HWC2_PFN_SET_PER_FRAME_METADATA setPerFrameMetadata; + HWC2_PFN_SET_LAYER_PER_FRAME_METADATA setLayerPerFrameMetadata; HWC2_PFN_GET_PER_FRAME_METADATA_KEYS getPerFrameMetadataKeys; HWC2_PFN_SET_READBACK_BUFFER setReadbackBuffer; HWC2_PFN_GET_READBACK_BUFFER_ATTRIBUTES getReadbackBufferAttributes; HWC2_PFN_GET_READBACK_BUFFER_FENCE getReadbackBufferFence; + HWC2_PFN_GET_RENDER_INTENTS getRenderIntents; + HWC2_PFN_SET_COLOR_MODE_WITH_RENDER_INTENT setColorModeWithRenderIntent; + HWC2_PFN_GET_DATASPACE_SATURATION_MATRIX getDataspaceSaturationMatrix; } mDispatch = {}; private: using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl; + using BaseType2_1::getColorModes; using BaseType2_1::mDevice; + using BaseType2_1::setColorMode; using BaseType2_1::setPowerMode; }; diff --git a/graphics/composer/2.2/utils/vts/Android.bp b/graphics/composer/2.2/utils/vts/Android.bp index 641fdcb76e..c6b524d234 100644 --- a/graphics/composer/2.2/utils/vts/Android.bp +++ b/graphics/composer/2.2/utils/vts/Android.bp @@ -26,10 +26,17 @@ cc_library_static { "android.hardware.graphics.composer@2.1-vts", "android.hardware.graphics.composer@2.2", ], + export_static_lib_headers: [ + "android.hardware.graphics.composer@2.1-vts", + ], header_libs: [ "android.hardware.graphics.composer@2.1-command-buffer", "android.hardware.graphics.composer@2.2-command-buffer", ], + export_header_lib_headers: [ + "android.hardware.graphics.composer@2.1-command-buffer", + "android.hardware.graphics.composer@2.2-command-buffer", + ], cflags: [ "-O0", "-g", diff --git a/graphics/composer/2.2/utils/vts/ComposerVts.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp index b536f6711e..9a035f6539 100644 --- a/graphics/composer/2.2/utils/vts/ComposerVts.cpp +++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp @@ -119,6 +119,41 @@ void ComposerClient_v2_2::getReadbackBufferFence(Display display, int32_t* outFe *outFence = 0; } +std::vector ComposerClient_v2_2::getColorModes(Display display) { + std::vector modes; + mClient_v2_2->getColorModes_2_2(display, [&](const auto& tmpError, const auto& tmpModes) { + ASSERT_EQ(Error::NONE, tmpError) << "failed to get color modes"; + modes = tmpModes; + }); + return modes; +} + +std::vector ComposerClient_v2_2::getRenderIntents(Display display, ColorMode mode) { + std::vector intents; + mClient_v2_2->getRenderIntents( + display, mode, [&](const auto& tmpError, const auto& tmpIntents) { + ASSERT_EQ(Error::NONE, tmpError) << "failed to get render intents"; + intents = tmpIntents; + }); + return intents; +} + +void ComposerClient_v2_2::setColorMode(Display display, ColorMode mode, RenderIntent intent) { + Error error = mClient_v2_2->setColorMode_2_2(display, mode, intent); + ASSERT_TRUE(error == Error::NONE || error == Error::UNSUPPORTED) << "failed to set color mode"; +} + +std::array ComposerClient_v2_2::getDataspaceSaturationMatrix(Dataspace dataspace) { + std::array matrix; + mClient_v2_2->getDataspaceSaturationMatrix( + dataspace, [&](const auto& tmpError, const auto& tmpMatrix) { + ASSERT_EQ(Error::NONE, tmpError) << "failed to get datasapce saturation matrix"; + std::copy_n(tmpMatrix.data(), matrix.size(), matrix.begin()); + }); + + return matrix; +} + } // namespace vts } // namespace V2_2 } // namespace composer diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h index eced69f2a4..5467011e45 100644 --- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h +++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h @@ -36,10 +36,11 @@ namespace composer { namespace V2_2 { 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; +using android::hardware::graphics::common::V1_1::ColorMode; +using android::hardware::graphics::common::V1_1::RenderIntent; using android::hardware::graphics::composer::V2_2::IComposer; using android::hardware::graphics::composer::V2_2::IComposerClient; @@ -72,6 +73,12 @@ class ComposerClient_v2_2 Dataspace* outDataspace); void getReadbackBufferFence(Display display, int32_t* outFence); + std::vector getColorModes(Display display); + std::vector getRenderIntents(Display display, ColorMode mode); + void setColorMode(Display display, ColorMode mode, RenderIntent intent); + + std::array getDataspaceSaturationMatrix(Dataspace dataspace); + private: sp mClient_v2_2; }; diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp index c49432966f..3103d10fc2 100644 --- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp +++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp @@ -33,11 +33,12 @@ namespace vts { namespace { using android::hardware::graphics::common::V1_0::BufferUsage; -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::PixelFormat; using android::hardware::graphics::common::V1_0::Transform; +using android::hardware::graphics::common::V1_1::ColorMode; +using android::hardware::graphics::common::V1_1::RenderIntent; using android::hardware::graphics::composer::V2_2::IComposerClient; using android::hardware::graphics::mapper::V2_0::IMapper; using android::hardware::graphics::mapper::V2_0::vts::Gralloc; @@ -146,9 +147,9 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { }; /** - * Test IComposerClient::Command::SET_PER_FRAME_METADATA. + * Test IComposerClient::Command::SET_LAYER_PER_FRAME_METADATA. */ -TEST_F(GraphicsComposerHidlCommandTest, SET_PER_FRAME_METADATA) { +TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_PER_FRAME_METADATA) { Layer layer; ASSERT_NO_FATAL_FAILURE(layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); @@ -182,7 +183,7 @@ TEST_F(GraphicsComposerHidlCommandTest, SET_PER_FRAME_METADATA) { hidlMetadata.push_back({IComposerClient::PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL, 78.0}); hidlMetadata.push_back( {IComposerClient::PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL, 62.0}); - mWriter->setPerFrameMetadata(hidlMetadata); + mWriter->setLayerPerFrameMetadata(hidlMetadata); execute(); } @@ -235,6 +236,56 @@ TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_FLOAT_COLOR) { mWriter->setLayerFloatColor(IComposerClient::FloatColor{0.0, 0.0, 0.0, 0.0}); } +/** + * Test IComposerClient::getDataspaceSaturationMatrix. + */ +TEST_F(GraphicsComposerHidlTest, getDataspaceSaturationMatrix) { + auto matrix = mComposerClient->getDataspaceSaturationMatrix(Dataspace::SRGB_LINEAR); + // the last row is known + ASSERT_EQ(0.0f, matrix[12]); + ASSERT_EQ(0.0f, matrix[13]); + ASSERT_EQ(0.0f, matrix[14]); + ASSERT_EQ(1.0f, matrix[15]); +} + +/** + * Test IComposerClient::getColorMode_2_2. + */ +TEST_F(GraphicsComposerHidlTest, GetColorMode_2_2) { + std::vector modes = mComposerClient->getColorModes(mPrimaryDisplay); + + auto nativeMode = std::find(modes.cbegin(), modes.cend(), ColorMode::NATIVE); + EXPECT_NE(modes.cend(), nativeMode); +} + +/** + * Test IComposerClient::getRenderIntent. + */ +TEST_F(GraphicsComposerHidlTest, GetRenderIntent) { + std::vector modes = mComposerClient->getColorModes(mPrimaryDisplay); + for (auto mode : modes) { + std::vector intents = + mComposerClient->getRenderIntents(mPrimaryDisplay, mode); + auto colorimetricIntent = + std::find(intents.cbegin(), intents.cend(), RenderIntent::COLORIMETRIC); + EXPECT_NE(intents.cend(), colorimetricIntent); + } +} + +/** + * Test IComposerClient::setColorMode_2_2. + */ +TEST_F(GraphicsComposerHidlTest, SetColorMode_2_2) { + std::vector modes = mComposerClient->getColorModes(mPrimaryDisplay); + for (auto mode : modes) { + std::vector intents = + mComposerClient->getRenderIntents(mPrimaryDisplay, mode); + for (auto intent : intents) { + mComposerClient->setColorMode(mPrimaryDisplay, mode, intent); + } + } +} + } // namespace } // namespace vts } // namespace V2_2