Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bf141483 authored by Kevin DuBois's avatar Kevin DuBois
Browse files

graphics: Add display color sampling interface.

Add a graphics.composer@2.3 interface that will expose
color sampling hardware present on some devices to the
framework. Adds:
  getDisplayedContentSamplingAttributes
  setDisplayedContentSamplingEnabled
  getDisplayedContentSample

Test: boot up pixel3
Test: VtsHalGraphicsComposerV2_3TargetTest on revved Pixel3 hwcomposer
Bug: 116028976
Change-Id: I88455f200590926f677c47efc39e9b6678e2318c
parent 1028dd74
Loading
Loading
Loading
Loading
+110 −0
Original line number Diff line number Diff line
@@ -161,6 +161,116 @@ interface IComposerClient extends @2.2::IComposerClient {
                               Dataspace dataspace)
                    generates (Error error);

    enum FormatColorComponent : uint8_t {
        /* The first component  (eg, for RGBA_8888, this is R) */
        FORMAT_COMPONENT_0 = 1 << 0,
        /* The second component (eg, for RGBA_8888, this is G) */
        FORMAT_COMPONENT_1 = 1 << 1,
        /* The third component  (eg, for RGBA_8888, this is B) */
        FORMAT_COMPONENT_2 = 1 << 2,
        /* The fourth component (eg, for RGBA_8888, this is A) */
        FORMAT_COMPONENT_3 = 1 << 3,
    };

    /**
     * Query for what types of color sampling the hardware supports.
     *
     * @param  display        is the display where the samples are collected.
     * @return error          is NONE upon success. Otherwise,
     *                        BAD_DISPLAY when an invalid display was passed in, or
     *                        UNSUPPORTED when there is no efficient way to sample.
     * @return format         The format of the sampled pixels.
     * @return dataspace      The dataspace of the sampled pixels.
     * @return componentMask  The mask of which components can be sampled.
     */
    getDisplayedContentSamplingAttributes(Display display)
               generates (Error error,
                          PixelFormat format,
                          Dataspace dataspace,
                          bitfield<FormatColorComponent> componentMask);

    /** DisplayedContentSampling values passed to setDisplayedContentSamplingEnabled. */
    enum DisplayedContentSampling : int32_t {
        INVALID = 0,

        /** Enable content sampling. */
        ENABLE = 1,

        /** Disable content sampling. */
        DISABLE = 2,
    };

    /**
     * Enables or disables the collection of color content statistics
     * on this display.
     *
     * Sampling occurs on the contents of the final composition on this display
     * (i.e., the contents presented on screen). Samples should be collected after all
     * color transforms have been applied.
     *
     * Sampling support is optional, and is set to DISABLE by default.
     * On each call to ENABLE, all collected statistics must be reset.
     *
     * Sample data can be queried via getDisplayedContentSample().
     *
     * @param display        is the display to which the sampling mode is set.
     * @param enabled        indicates whether to enable or disable sampling.
     * @param componentMask  The mask of which components should be sampled. If zero, all supported
     *                       components are to be enabled.
     * @param maxFrames      is the maximum number of frames that should be stored before discard.
     *                       The sample represents the most-recently posted frames.
     * @return error      is NONE upon success. Otherwise,
     *                    BAD_DISPLAY when an invalid display handle was passed in,
     *                    BAD_PARAMETER when enabled was an invalid value, or
     *                    NO_RESOURCES when the requested ringbuffer size via maxFrames was
     *                                 not available.
     *                    UNSUPPORTED when there is no efficient way to sample.
     */
    setDisplayedContentSamplingEnabled(
        Display display, DisplayedContentSampling enable,
        bitfield<FormatColorComponent> componentMask, uint64_t maxFrames)
        generates (Error error);

    /**
     * Collects the results of display content color sampling for display.
     *
     * Collection of data can occur whether the sampling is in ENABLE or
     * DISABLE state.
     *
     * @param  display     is the display to which the sampling is collected.
     * @param  maxFrames   is the maximum number of frames that should be represented in the sample.
     *                     The sample represents the most-recently posted frames.
     *                     If maxFrames is 0, all frames are to be represented by the sample.
     * @param  timestamp   is the timestamp after which any frames were posted that should be
     *                     included in the sample. Timestamp is CLOCK_MONOTONIC.
     *                     If timestamp is 0, do not filter from the sample by time.
     * @return error       is NONE upon success. Otherwise,
     *                     BAD_DISPLAY   when an invalid display was passed in, or
     *                     UNSUPPORTED   when there is no efficient way to sample, or
     *                     BAD_PARAMETER when the component is not supported by the hardware.
     * @return frameCount  The number of frames represented by this sample.
     * @return sampleComponent0 is a histogram counting how many times a pixel of a given value
     *                     was displayed onscreen for FORMAT_COMPONENT_0.
     *                     The buckets of the histogram are evenly weighted, the number of buckets
     *                     is device specific.
     *                     eg, for RGBA_8888, if sampleComponent0 is {10, 6, 4, 1} this means that
     *                     10 red pixels were displayed onscreen in range 0x00->0x3F, 6 red pixels
     *                     were displayed onscreen in range 0x40->0x7F, etc.
     * @return sampleComponent1 is the same sample definition as sampleComponent0,
     *                     but for FORMAT_COMPONENT_1.
     * @return sampleComponent2 is the same sample definition as sampleComponent0,
     *                     but for FORMAT_COMPONENT_2.
     * @return sampleComponent3 is the same sample definition as sampleComponent0,
     *                     but for FORMAT_COMPONENT_3.
     */
    getDisplayedContentSample(Display display, uint64_t maxFrames, uint64_t timestamp)
               generates (Error error,
                          uint64_t frameCount,
                          vec<uint64_t> sampleComponent0,
                          vec<uint64_t> sampleComponent1,
                          vec<uint64_t> sampleComponent2,
                          vec<uint64_t> sampleComponent3);

    /**
     * Executes commands from the input command message queue. Return values
     * generated by the input commands are written to the output command
+36 −0
Original line number Diff line number Diff line
@@ -91,6 +91,42 @@ class ComposerClientImpl : public V2_2::hal::detail::ComposerClientImpl<Interfac
        return Void();
    }

    Return<void> getDisplayedContentSamplingAttributes(
        uint64_t display,
        IComposerClient::getDisplayedContentSamplingAttributes_cb hidl_cb) override {
        common::V1_1::PixelFormat format;
        common::V1_2::Dataspace dataspace;
        hidl_bitfield<IComposerClient::FormatColorComponent> componentMask;
        Error error =
            mHal->getDisplayedContentSamplingAttributes(display, format, dataspace, componentMask);
        hidl_cb(error, format, dataspace, componentMask);
        return Void();
    }

    Return<Error> setDisplayedContentSamplingEnabled(
        uint64_t display, IComposerClient::DisplayedContentSampling enable,
        hidl_bitfield<IComposerClient::FormatColorComponent> componentMask,
        uint64_t maxFrames) override {
        return mHal->setDisplayedContentSamplingEnabled(display, enable, componentMask, maxFrames);
    }

    Return<void> getDisplayedContentSample(
        uint64_t display, uint64_t maxFrames, uint64_t timestamp,
        IComposerClient::getDisplayedContentSample_cb hidl_cb) override {
        uint64_t frameCount;
        hidl_vec<uint64_t> sampleComponent0;
        hidl_vec<uint64_t> sampleComponent1;
        hidl_vec<uint64_t> sampleComponent2;
        hidl_vec<uint64_t> sampleComponent3;

        Error error = mHal->getDisplayedContentSample(display, maxFrames, timestamp, frameCount,
                                                      sampleComponent0, sampleComponent1,
                                                      sampleComponent2, sampleComponent3);
        hidl_cb(error, frameCount, sampleComponent0, sampleComponent1, sampleComponent2,
                sampleComponent3);
        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);
+12 −0
Original line number Diff line number Diff line
@@ -72,6 +72,18 @@ class ComposerHal : public V2_2::hal::ComposerHal {
    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;
    virtual Error getDisplayedContentSamplingAttributes(
        uint64_t display, PixelFormat& format, Dataspace& dataspace,
        hidl_bitfield<IComposerClient::FormatColorComponent>& componentMask) = 0;
    virtual Error setDisplayedContentSamplingEnabled(
        uint64_t display, IComposerClient::DisplayedContentSampling enable,
        hidl_bitfield<IComposerClient::FormatColorComponent> componentMask, uint64_t maxFrames) = 0;
    virtual Error getDisplayedContentSample(uint64_t display, uint64_t maxFrames,
                                            uint64_t timestamp, uint64_t& frameCount,
                                            hidl_vec<uint64_t>& sampleComponent0,
                                            hidl_vec<uint64_t>& sampleComponent1,
                                            hidl_vec<uint64_t>& sampleComponent2,
                                            hidl_vec<uint64_t>& sampleComponent3) = 0;
};

}  // namespace hal
+68 −0
Original line number Diff line number Diff line
@@ -104,6 +104,65 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl<Hal> {
        return static_cast<Error>(err);
    }

    Error getDisplayedContentSamplingAttributes(
        uint64_t display, PixelFormat& format, Dataspace& dataspace,
        hidl_bitfield<IComposerClient::FormatColorComponent>& componentMask) override {
        if (!mDispatch.getDisplayedContentSamplingAttributes) {
            return Error::UNSUPPORTED;
        }
        int32_t formatRaw = 0;
        int32_t dataspaceRaw = 0;
        uint8_t componentMaskRaw = 0;
        int32_t errorRaw = mDispatch.getDisplayedContentSamplingAttributes(
            mDevice, display, &formatRaw, &dataspaceRaw, &componentMaskRaw);
        auto error = static_cast<Error>(errorRaw);
        if (error == Error::NONE) {
            format = static_cast<PixelFormat>(formatRaw);
            dataspace = static_cast<Dataspace>(dataspaceRaw);
            componentMask =
                static_cast<hidl_bitfield<IComposerClient::FormatColorComponent>>(componentMaskRaw);
        }
        return error;
    };

    Error setDisplayedContentSamplingEnabled(
        uint64_t display, IComposerClient::DisplayedContentSampling enable,
        hidl_bitfield<IComposerClient::FormatColorComponent> componentMask,
        uint64_t maxFrames) override {
        if (!mDispatch.setDisplayedContentSamplingEnabled) {
            return Error::UNSUPPORTED;
        }
        return static_cast<Error>(mDispatch.setDisplayedContentSamplingEnabled(
            mDevice, display, static_cast<int32_t>(enable), componentMask, maxFrames));
    }

    Error getDisplayedContentSample(uint64_t display, uint64_t maxFrames, uint64_t timestamp,
                                    uint64_t& frameCount, hidl_vec<uint64_t>& sampleComponent0,
                                    hidl_vec<uint64_t>& sampleComponent1,
                                    hidl_vec<uint64_t>& sampleComponent2,
                                    hidl_vec<uint64_t>& sampleComponent3) override {
        if (!mDispatch.getDisplayedContentSample) {
            return Error::UNSUPPORTED;
        }

        int32_t size[4] = {0};
        auto errorRaw = mDispatch.getDisplayedContentSample(mDevice, display, maxFrames, timestamp,
                                                            &frameCount, size, nullptr);
        if (errorRaw != HWC2_ERROR_NONE) {
            return static_cast<Error>(errorRaw);
        }

        sampleComponent0.resize(size[0]);
        sampleComponent1.resize(size[1]);
        sampleComponent2.resize(size[2]);
        sampleComponent3.resize(size[3]);
        uint64_t* samples[] = {sampleComponent0.data(), sampleComponent1.data(),
                               sampleComponent2.data(), sampleComponent3.data()};
        errorRaw = mDispatch.getDisplayedContentSample(mDevice, display, maxFrames, timestamp,
                                                       &frameCount, size, samples);
        return static_cast<Error>(errorRaw);
    }

   protected:
    bool initDispatch() override {
        if (!BaseType2_2::initDispatch()) {
@@ -114,6 +173,12 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl<Hal> {
                                   &mDispatch.getDisplayIdentificationData);
        this->initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_COLOR_TRANSFORM,
                                   &mDispatch.setLayerColorTransform);
        this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES,
                                   &mDispatch.getDisplayedContentSamplingAttributes);
        this->initOptionalDispatch(HWC2_FUNCTION_SET_DISPLAYED_CONTENT_SAMPLING_ENABLED,
                                   &mDispatch.setDisplayedContentSamplingEnabled);
        this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAYED_CONTENT_SAMPLE,
                                   &mDispatch.getDisplayedContentSample);
        return true;
    }

@@ -121,6 +186,9 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl<Hal> {
    struct {
        HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA getDisplayIdentificationData;
        HWC2_PFN_SET_LAYER_COLOR_TRANSFORM setLayerColorTransform;
        HWC2_PFN_GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES getDisplayedContentSamplingAttributes;
        HWC2_PFN_SET_DISPLAYED_CONTENT_SAMPLING_ENABLED setDisplayedContentSamplingEnabled;
        HWC2_PFN_GET_DISPLAYED_CONTENT_SAMPLE getDisplayedContentSample;
    } mDispatch = {};

    using BaseType2_2 = V2_2::passthrough::detail::HwcHalImpl<Hal>;
+42 −0
Original line number Diff line number Diff line
@@ -108,6 +108,48 @@ bool ComposerClient::getClientTargetSupport_2_3(Display display, uint32_t width,
    return error == Error::NONE;
}

Error ComposerClient::getDisplayedContentSamplingAttributes(
    uint64_t display, PixelFormat& format, Dataspace& dataspace,
    hidl_bitfield<IComposerClient::FormatColorComponent>& componentMask) {
    auto error = Error::BAD_PARAMETER;
    mClient->getDisplayedContentSamplingAttributes(
        display, [&](const auto& tmpError, const auto& tmpFormat, const auto& tmpDataspace,
                     const auto& tmpComponentMask) {
            error = tmpError;
            format = tmpFormat;
            dataspace = tmpDataspace;
            componentMask = tmpComponentMask;
        });
    return error;
}

Error ComposerClient::setDisplayedContentSamplingEnabled(
    uint64_t display, IComposerClient::DisplayedContentSampling enable,
    hidl_bitfield<IComposerClient::FormatColorComponent> componentMask, uint64_t maxFrames) {
    return mClient->setDisplayedContentSamplingEnabled(display, enable, componentMask, maxFrames);
}

Error ComposerClient::getDisplayedContentSample(uint64_t display, uint64_t maxFrames,
                                                uint64_t timestamp, uint64_t& frameCount,
                                                hidl_vec<uint64_t>& sampleComponent0,
                                                hidl_vec<uint64_t>& sampleComponent1,
                                                hidl_vec<uint64_t>& sampleComponent2,
                                                hidl_vec<uint64_t>& sampleComponent3) {
    auto error = Error::BAD_PARAMETER;
    mClient->getDisplayedContentSample(
        display, maxFrames, timestamp,
        [&](const auto& tmpError, const auto& tmpFrameCount, const auto& tmpSamples0,
            const auto& tmpSamples1, const auto& tmpSamples2, const auto& tmpSamples3) {
            error = tmpError;
            frameCount = tmpFrameCount;
            sampleComponent0 = tmpSamples0;
            sampleComponent1 = tmpSamples1;
            sampleComponent2 = tmpSamples2;
            sampleComponent3 = tmpSamples3;
        });
    return error;
}

}  // namespace vts
}  // namespace V2_3
}  // namespace composer
Loading