diff options
| author | 2018-04-25 14:34:31 -0700 | |
|---|---|---|
| committer | 2018-05-02 10:56:11 -0700 | |
| commit | fb069305e90947aeb76b72527f23aa24564f3c87 (patch) | |
| tree | 45a22b91bce96a44053931f0396ae81f6b6fc3ce | |
| parent | af0c783042eb89b58abb28bda87e4dd298af725f (diff) | |
[SurfaceFlinger] Adapt min/max luminance from hardware composer.
The luminance capability of the display is very important to HDR content.
Previously, the minimum and maximum luminance were assumed as 0.0 and 500.0
respectively. This patch adapts the value returned from hardware composer and
plumbs the value to RenderEngine. If hardware composer doesn't return valid
values, 0.0 and 500.0 are still used as minimum and maximum luminance
respectively.
BUG: 73825729
BUG: 78574325
Test: Build, flash, watch video.
Change-Id: Ie1dc93f5cca7068580d6ae19da43346491196d7c
| -rw-r--r-- | libs/ui/HdrCapabilities.cpp | 1 | ||||
| -rw-r--r-- | services/surfaceflinger/DisplayDevice.cpp | 23 | ||||
| -rw-r--r-- | services/surfaceflinger/DisplayDevice.h | 16 | ||||
| -rw-r--r-- | services/surfaceflinger/RenderArea.h | 1 | ||||
| -rw-r--r-- | services/surfaceflinger/RenderEngine/Description.cpp | 4 | ||||
| -rw-r--r-- | services/surfaceflinger/RenderEngine/Description.h | 3 | ||||
| -rw-r--r-- | services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp | 4 | ||||
| -rw-r--r-- | services/surfaceflinger/RenderEngine/GLES20RenderEngine.h | 23 | ||||
| -rw-r--r-- | services/surfaceflinger/RenderEngine/Program.cpp | 4 | ||||
| -rw-r--r-- | services/surfaceflinger/RenderEngine/Program.h | 3 | ||||
| -rw-r--r-- | services/surfaceflinger/RenderEngine/ProgramCache.cpp | 6 | ||||
| -rw-r--r-- | services/surfaceflinger/RenderEngine/RenderEngine.h | 3 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 41 | ||||
| -rw-r--r-- | services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h | 1 |
14 files changed, 91 insertions, 42 deletions
diff --git a/libs/ui/HdrCapabilities.cpp b/libs/ui/HdrCapabilities.cpp index 50f9bf13fd..a36911d1cf 100644 --- a/libs/ui/HdrCapabilities.cpp +++ b/libs/ui/HdrCapabilities.cpp @@ -27,7 +27,6 @@ HdrCapabilities::~HdrCapabilities() = default; HdrCapabilities::HdrCapabilities(HdrCapabilities&& other) = default; HdrCapabilities& HdrCapabilities::operator=(HdrCapabilities&& other) = default; - size_t HdrCapabilities::getFlattenedSize() const { return sizeof(mMaxLuminance) + sizeof(mMaxAverageLuminance) + diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 7c6302e70a..00f8cc9c5c 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -108,7 +108,8 @@ DisplayDevice::DisplayDevice( mSupportedPerFrameMetadata(supportedPerFrameMetadata) { // clang-format on - for (Hdr hdrType : hdrCapabilities.getSupportedHdrTypes()) { + std::vector<Hdr> types = hdrCapabilities.getSupportedHdrTypes(); + for (Hdr hdrType : types) { switch (hdrType) { case Hdr::HDR10: mHasHdr10 = true; @@ -124,6 +125,26 @@ DisplayDevice::DisplayDevice( } } + float minLuminance = hdrCapabilities.getDesiredMinLuminance(); + float maxLuminance = hdrCapabilities.getDesiredMaxLuminance(); + float maxAverageLuminance = hdrCapabilities.getDesiredMaxAverageLuminance(); + + minLuminance = minLuminance <= 0.0 ? sDefaultMinLumiance : minLuminance; + maxLuminance = maxLuminance <= 0.0 ? sDefaultMaxLumiance : maxLuminance; + maxAverageLuminance = maxAverageLuminance <= 0.0 ? sDefaultMaxLumiance : maxAverageLuminance; + if (this->hasWideColorGamut()) { + // insert HDR10/HLG as we will force client composition for HDR10/HLG + // layers + if (!hasHDR10Support()) { + types.push_back(Hdr::HDR10); + } + + if (!hasHLGSupport()) { + types.push_back(Hdr::HLG); + } + } + mHdrCapabilities = HdrCapabilities(types, maxLuminance, maxAverageLuminance, minLuminance); + // initialize the display orientation transform. setProjection(DisplayState::eOrientationDefault, mViewport, mFrame); } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index df5d945405..1df8c49b1f 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -27,6 +27,7 @@ #include <gui/ISurfaceComposer.h> #include <hardware/hwcomposer_defs.h> #include <ui/GraphicTypes.h> +#include <ui/HdrCapabilities.h> #include <ui/Region.h> #include <utils/RefBase.h> #include <utils/Mutex.h> @@ -53,6 +54,9 @@ class HWComposer; class DisplayDevice : public LightRefBase<DisplayDevice> { public: + constexpr static float sDefaultMinLumiance = 0.0; + constexpr static float sDefaultMaxLumiance = 500.0; + // region in layer-stack space mutable Region dirtyRegion; // region in screen space @@ -141,6 +145,13 @@ public: bool hasHDR10Support() const { return mHasHdr10; } bool hasHLGSupport() const { return mHasHLG; } bool hasDolbyVisionSupport() const { return mHasDolbyVision; } + // The returned HdrCapabilities is the combination of HDR capabilities from + // hardware composer and RenderEngine. When the DisplayDevice supports wide + // color gamut, RenderEngine is able to simulate HDR support in Display P3 + // color space for both PQ and HLG HDR contents. The minimum and maximum + // luminance will be set to sDefaultMinLumiance and sDefaultMaxLumiance + // respectively if hardware composer doesn't return meaningful values. + const HdrCapabilities& getHdrCapabilities() const { return mHdrCapabilities; } void swapBuffers(HWComposer& hwc) const; @@ -261,7 +272,7 @@ private: bool mHasHdr10; bool mHasHLG; bool mHasDolbyVision; - + HdrCapabilities mHdrCapabilities; const int32_t mSupportedPerFrameMetadata; }; @@ -309,6 +320,9 @@ public: ui::Dataspace getDataSpace() const override { return mDevice->getCompositionDataSpace(); } + float getDisplayMaxLuminance() const override { + return mDevice->getHdrCapabilities().getDesiredMaxLuminance(); + } private: const sp<const DisplayDevice> mDevice; diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index 36306773f7..4694403c2d 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -32,6 +32,7 @@ public: virtual Rect getSourceCrop() const = 0; virtual bool getWideColorSupport() const = 0; virtual ui::Dataspace getDataSpace() const = 0; + virtual float getDisplayMaxLuminance() const = 0; virtual void render(std::function<void()> drawLayers) { drawLayers(); } diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp index 323bdb2b41..0ccdbc4364 100644 --- a/services/surfaceflinger/RenderEngine/Description.cpp +++ b/services/surfaceflinger/RenderEngine/Description.cpp @@ -73,4 +73,8 @@ void Description::setOutputTransferFunction(TransferFunction transferFunction) { mOutputTransferFunction = transferFunction; } +void Description::setDisplayMaxLuminance(const float maxLuminance) { + mDisplayMaxLuminance = maxLuminance; +} + } /* namespace android */ diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h index 5854ba49d1..b09e3a88ab 100644 --- a/services/surfaceflinger/RenderEngine/Description.h +++ b/services/surfaceflinger/RenderEngine/Description.h @@ -55,6 +55,7 @@ public: }; void setInputTransferFunction(TransferFunction transferFunction); void setOutputTransferFunction(TransferFunction transferFunction); + void setDisplayMaxLuminance(const float maxLuminance); private: friend class Program; @@ -83,6 +84,8 @@ private: // transfer functions for the input/output TransferFunction mInputTransferFunction = TransferFunction::LINEAR; TransferFunction mOutputTransferFunction = TransferFunction::LINEAR; + + float mDisplayMaxLuminance; }; } /* namespace android */ diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index 6e0fa329f1..8e3c837dd7 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -224,6 +224,10 @@ void GLES20RenderEngine::setOutputDataSpace(Dataspace dataspace) { mOutputDataSpace = dataspace; } +void GLES20RenderEngine::setDisplayMaxLuminance(const float maxLuminance) { + mState.setDisplayMaxLuminance(maxLuminance); +} + void GLES20RenderEngine::setupLayerTexturing(const Texture& texture) { GLuint target = texture.getTextureTarget(); glBindTexture(target, texture.getTextureName()); diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h index 99da19d6b1..7177aad032 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h @@ -75,17 +75,7 @@ protected: void setSourceY410BT2020(bool enable) override; void setSourceDataSpace(ui::Dataspace source) override; void setOutputDataSpace(ui::Dataspace dataspace) override; - - // Current dataspace of layer being rendered - ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN; - - // Current output dataspace of the render engine - ui::Dataspace mOutputDataSpace = ui::Dataspace::UNKNOWN; - - // Currently only supporting sRGB, BT2020 and DisplayP3 color spaces - const bool mPlatformHasWideColor = false; - mat4 mSrgbToDisplayP3; - mat4 mBt2020ToDisplayP3; + void setDisplayMaxLuminance(const float maxLuminance) override; virtual void setupLayerTexturing(const Texture& texture); virtual void setupLayerBlackedOut(); @@ -98,6 +88,17 @@ protected: virtual size_t getMaxTextureSize() const; virtual size_t getMaxViewportDims() const; + + // Current dataspace of layer being rendered + ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN; + + // Current output dataspace of the render engine + ui::Dataspace mOutputDataSpace = ui::Dataspace::UNKNOWN; + + // Currently only supporting sRGB, BT2020 and DisplayP3 color spaces + const bool mPlatformHasWideColor = false; + mat4 mSrgbToDisplayP3; + mat4 mBt2020ToDisplayP3; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/Program.cpp index 225bcf0327..e5261c28f7 100644 --- a/services/surfaceflinger/RenderEngine/Program.cpp +++ b/services/surfaceflinger/RenderEngine/Program.cpp @@ -64,6 +64,7 @@ Program::Program(const ProgramCache::Key& /*needs*/, const char* vertex, const c mTextureMatrixLoc = glGetUniformLocation(programId, "texture"); mSamplerLoc = glGetUniformLocation(programId, "sampler"); mColorLoc = glGetUniformLocation(programId, "color"); + mDisplayMaxLuminanceLoc = glGetUniformLocation(programId, "displayMaxLuminance"); // set-up the default values for our uniforms glUseProgram(programId); @@ -136,6 +137,9 @@ void Program::setUniforms(const Description& desc) { if (mColorMatrixLoc >= 0) { glUniformMatrix4fv(mColorMatrixLoc, 1, GL_FALSE, desc.mColorMatrix.asArray()); } + if (mDisplayMaxLuminanceLoc >= 0) { + glUniform1f(mDisplayMaxLuminanceLoc, desc.mDisplayMaxLuminance); + } // these uniforms are always present glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, desc.mProjectionMatrix.asArray()); } diff --git a/services/surfaceflinger/RenderEngine/Program.h b/services/surfaceflinger/RenderEngine/Program.h index 6e57fdd56f..55b9cdd93b 100644 --- a/services/surfaceflinger/RenderEngine/Program.h +++ b/services/surfaceflinger/RenderEngine/Program.h @@ -80,6 +80,9 @@ private: /* location of the color uniform */ GLint mColorLoc; + + /* location of display luminance uniform */ + GLint mDisplayMaxLuminanceLoc; }; } /* namespace android */ diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp index fb63296de3..5d5462f728 100644 --- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp +++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp @@ -247,7 +247,7 @@ void ProgramCache::generateOOTF(Formatter& fs, const Key& needs) { const float maxMasteringLumi = 1000.0; const float maxContentLumi = 1000.0; const float maxInLumi = min(maxMasteringLumi, maxContentLumi); - const float maxOutLumi = 500.0; + const float maxOutLumi = displayMaxLuminance; // Calculate Y value in XYZ color space. float colorY = CalculateY(color); @@ -443,6 +443,10 @@ String8 ProgramCache::generateFragmentShader(const Key& needs) { if (needs.hasColorMatrix()) { fs << "uniform mat4 colorMatrix;"; + // Currently, only the OOTF of BT2020 PQ needs display maximum luminance. + if (needs.getInputTF() == Key::INPUT_TF_ST2084) { + fs << "uniform float displayMaxLuminance"; + } generateEOTF(fs, needs); generateOOTF(fs, needs); diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index f78b230778..df9e6a74a2 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -117,10 +117,11 @@ public: virtual void disableTexturing() = 0; virtual void disableBlending() = 0; - // wide color support + // HDR and wide color gamut support virtual void setSourceY410BT2020(bool enable) = 0; virtual void setSourceDataSpace(ui::Dataspace source) = 0; virtual void setOutputDataSpace(ui::Dataspace dataspace) = 0; + virtual void setDisplayMaxLuminance(const float maxLuminance) = 0; // drawing virtual void drawMesh(const Mesh& mesh) = 0; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e12d7ca73d..f736c8cfda 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1119,31 +1119,14 @@ status_t SurfaceFlinger::getHdrCapabilities(const sp<IBinder>& display, return BAD_VALUE; } - HdrCapabilities capabilities; - int status = getBE().mHwc->getHdrCapabilities( - displayDevice->getHwcDisplayId(), &capabilities); - if (status == NO_ERROR) { - if (displayDevice->hasWideColorGamut()) { - std::vector<Hdr> types = capabilities.getSupportedHdrTypes(); - // insert HDR10/HLG as we will force client composition for HDR10/HLG - // layers - if (!displayDevice->hasHDR10Support()) { - types.push_back(Hdr::HDR10); - } - if (!displayDevice->hasHLGSupport()) { - types.push_back(Hdr::HLG); - } - - *outCapabilities = HdrCapabilities(types, - capabilities.getDesiredMaxLuminance(), - capabilities.getDesiredMaxAverageLuminance(), - capabilities.getDesiredMinLuminance()); - } else { - *outCapabilities = std::move(capabilities); - } - } else { - return BAD_VALUE; - } + // At this point the DisplayDeivce should already be set up, + // meaning the luminance information is already queried from + // hardware composer and stored properly. + const HdrCapabilities& capabilities = displayDevice->getHdrCapabilities(); + *outCapabilities = HdrCapabilities(capabilities.getSupportedHdrTypes(), + capabilities.getDesiredMaxLuminance(), + capabilities.getDesiredMaxAverageLuminance(), + capabilities.getDesiredMinLuminance()); return NO_ERROR; } @@ -2917,6 +2900,8 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& displayDev outputDataspace = displayDevice->getCompositionDataSpace(); } getBE().mRenderEngine->setOutputDataSpace(outputDataspace); + getBE().mRenderEngine->setDisplayMaxLuminance( + displayDevice->getHdrCapabilities().getDesiredMaxLuminance()); if (!displayDevice->makeCurrent()) { ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s", @@ -4721,6 +4706,9 @@ status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder, } bool getWideColorSupport() const override { return false; } Dataspace getDataSpace() const override { return Dataspace::UNKNOWN; } + float getDisplayMaxLuminance() const override { + return DisplayDevice::sDefaultMaxLumiance; + } class ReparentForDrawing { public: @@ -4923,7 +4911,8 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, if (renderArea.getWideColorSupport()) { outputDataspace = renderArea.getDataSpace(); } - getBE().mRenderEngine->setOutputDataSpace(outputDataspace); + engine.setOutputDataSpace(outputDataspace); + engine.setDisplayMaxLuminance(renderArea.getDisplayMaxLuminance()); // make sure to clear all GL error flags engine.checkErrors(); diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h index 9bb2a3c961..29cd2d545a 100644 --- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h +++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h @@ -66,6 +66,7 @@ public: MOCK_METHOD1(setSourceY410BT2020, void(bool)); MOCK_METHOD1(setSourceDataSpace, void(ui::Dataspace)); MOCK_METHOD1(setOutputDataSpace, void(ui::Dataspace)); + MOCK_METHOD1(setDisplayMaxLuminance, void(const float)); MOCK_METHOD2(bindNativeBufferAsFrameBuffer, void(ANativeWindowBuffer*, RE::BindNativeBufferAsFramebuffer*)); MOCK_METHOD1(unbindNativeBufferAsFrameBuffer, void(RE::BindNativeBufferAsFramebuffer*)); |