diff options
-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*)); |