Merge "[SurfaceFlinger] Adapt min/max luminance from hardware composer." into pi-dev
am: 8c53323232
Change-Id: Ied84bbac9df6ca5c3521c2b3ddbe441e715fef40
diff --git a/libs/ui/HdrCapabilities.cpp b/libs/ui/HdrCapabilities.cpp
index 50f9bf1..a36911d 100644
--- a/libs/ui/HdrCapabilities.cpp
+++ b/libs/ui/HdrCapabilities.cpp
@@ -27,7 +27,6 @@
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 7c6302e..00f8cc9 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -108,7 +108,8 @@
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 @@
}
}
+ 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 df5d945..1df8c49 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 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 @@
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 @@
bool mHasHdr10;
bool mHasHLG;
bool mHasDolbyVision;
-
+ HdrCapabilities mHdrCapabilities;
const int32_t mSupportedPerFrameMetadata;
};
@@ -309,6 +320,9 @@
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 3630677..4694403 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -32,6 +32,7 @@
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 323bdb2..0ccdbc4 100644
--- a/services/surfaceflinger/RenderEngine/Description.cpp
+++ b/services/surfaceflinger/RenderEngine/Description.cpp
@@ -73,4 +73,8 @@
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 5854ba4..b09e3a8 100644
--- a/services/surfaceflinger/RenderEngine/Description.h
+++ b/services/surfaceflinger/RenderEngine/Description.h
@@ -55,6 +55,7 @@
};
void setInputTransferFunction(TransferFunction transferFunction);
void setOutputTransferFunction(TransferFunction transferFunction);
+ void setDisplayMaxLuminance(const float maxLuminance);
private:
friend class Program;
@@ -83,6 +84,8 @@
// 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 6e0fa32..8e3c837 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -224,6 +224,10 @@
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 99da19d..7177aad 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -75,17 +75,7 @@
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 @@
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 225bcf0..e5261c2 100644
--- a/services/surfaceflinger/RenderEngine/Program.cpp
+++ b/services/surfaceflinger/RenderEngine/Program.cpp
@@ -64,6 +64,7 @@
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 @@
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 6e57fdd..55b9cdd 100644
--- a/services/surfaceflinger/RenderEngine/Program.h
+++ b/services/surfaceflinger/RenderEngine/Program.h
@@ -80,6 +80,9 @@
/* 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 fb63296..5d5462f 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -247,7 +247,7 @@
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 @@
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 f78b230..df9e6a7 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -117,10 +117,11 @@
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 e12d7ca..f736c8c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1119,31 +1119,14 @@
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 @@
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 @@
}
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 @@
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 9bb2a3c..29cd2d5 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
@@ -66,6 +66,7 @@
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*));