summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Chia-I Wu <olv@google.com> 2018-01-11 08:54:38 -0800
committer Chia-I Wu <olv@google.com> 2018-01-22 12:18:24 -0800
commit5c6e46353676b4fd647317fde28c413d8ffe3565 (patch)
tree7dfd0f945db8ab01ab1ebfd7cfa4079a04a6c58b
parent131d3760a0437fac08ff4cc384640b7ca1802d17 (diff)
surfaceflinger: always advertise HDR10 when wide color is available
For HWC that already adversises HDR10 support, this has no effect. Otherwise, SurfaceFlinger will insert HDR10 into HdrCapabilities when wide color is supported. SurfaceFlinger simulates HDR10 support by switching the color mode to DISPLAY_P3 and forcing client composition for HDR10 layers. It also has a special path to treat RGBA_1010102/BT2020_PQ as Y410/BT2020_PQ in RenderEngine when the buffer is from media. Test: manual Change-Id: Ib5f18e0100f5610ee65218108bdb9843baccbe98
-rw-r--r--libs/gui/BufferItem.cpp6
-rw-r--r--libs/gui/BufferQueueProducer.cpp1
-rw-r--r--libs/gui/include/gui/BufferItem.h3
-rw-r--r--services/surfaceflinger/BufferLayer.cpp9
-rw-r--r--services/surfaceflinger/BufferLayerConsumer.cpp7
-rw-r--r--services/surfaceflinger/BufferLayerConsumer.h5
-rw-r--r--services/surfaceflinger/DisplayDevice.cpp5
-rw-r--r--services/surfaceflinger/DisplayDevice.h4
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp39
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h3
10 files changed, 74 insertions, 8 deletions
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp
index f7409dc344..f50379b3ed 100644
--- a/libs/gui/BufferItem.cpp
+++ b/libs/gui/BufferItem.cpp
@@ -55,7 +55,8 @@ BufferItem::BufferItem() :
mSurfaceDamage(),
mAutoRefresh(false),
mQueuedBuffer(true),
- mIsStale(false) {
+ mIsStale(false),
+ mApi(0) {
}
BufferItem::~BufferItem() {}
@@ -84,6 +85,7 @@ size_t BufferItem::getPodSize() const {
addAligned(size, mAutoRefresh);
addAligned(size, mQueuedBuffer);
addAligned(size, mIsStale);
+ addAligned(size, mApi);
return size;
}
@@ -177,6 +179,7 @@ status_t BufferItem::flatten(
writeAligned(buffer, size, mAutoRefresh);
writeAligned(buffer, size, mQueuedBuffer);
writeAligned(buffer, size, mIsStale);
+ writeAligned(buffer, size, mApi);
return NO_ERROR;
}
@@ -247,6 +250,7 @@ status_t BufferItem::unflatten(
readAligned(buffer, size, mAutoRefresh);
readAligned(buffer, size, mQueuedBuffer);
readAligned(buffer, size, mIsStale);
+ readAligned(buffer, size, mApi);
return NO_ERROR;
}
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index add857c350..e583b40632 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -878,6 +878,7 @@ status_t BufferQueueProducer::queueBuffer(int slot,
item.mSurfaceDamage = surfaceDamage;
item.mQueuedBuffer = true;
item.mAutoRefresh = mCore->mSharedBufferMode && mCore->mAutoRefresh;
+ item.mApi = mCore->mConnectedApi;
mStickyTransform = stickyTransform;
diff --git a/libs/gui/include/gui/BufferItem.h b/libs/gui/include/gui/BufferItem.h
index 7740b9f095..218bb424fb 100644
--- a/libs/gui/include/gui/BufferItem.h
+++ b/libs/gui/include/gui/BufferItem.h
@@ -127,6 +127,9 @@ class BufferItem : public Flattenable<BufferItem> {
// Indicates that this BufferItem contains a stale buffer which has already
// been released by the BufferQueue.
bool mIsStale;
+
+ // Indicates the API (NATIVE_WINDOW_API_xxx) that queues the buffer.
+ int mApi;
};
} // namespace android
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index d860f58509..ab6a559aad 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -821,8 +821,17 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT
engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), false /* disableTexture */,
getColor());
engine.setSourceDataSpace(mCurrentState.dataSpace);
+
+ if (mCurrentState.dataSpace == HAL_DATASPACE_BT2020_PQ &&
+ mConsumer->getCurrentApi() == NATIVE_WINDOW_API_MEDIA &&
+ getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102) {
+ engine.setSourceY410BT2020(true);
+ }
+
engine.drawMesh(getBE().mMesh);
engine.disableBlending();
+
+ engine.setSourceY410BT2020(false);
}
uint32_t BufferLayer::getProducerStickyTransform() const {
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index 8f5c9c740b..4d9b43f52e 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -68,6 +68,7 @@ BufferLayerConsumer::BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq, R
mCurrentFrameNumber(0),
mCurrentTransformToDisplayInverse(false),
mCurrentSurfaceDamage(),
+ mCurrentApi(0),
mDefaultWidth(1),
mDefaultHeight(1),
mFilteringEnabled(true),
@@ -346,6 +347,7 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item,
mCurrentFrameNumber = item.mFrameNumber;
mCurrentTransformToDisplayInverse = item.mTransformToDisplayInverse;
mCurrentSurfaceDamage = item.mSurfaceDamage;
+ mCurrentApi = item.mApi;
computeCurrentTransformMatrixLocked();
@@ -469,6 +471,11 @@ const Region& BufferLayerConsumer::getSurfaceDamage() const {
return mCurrentSurfaceDamage;
}
+int BufferLayerConsumer::getCurrentApi() const {
+ Mutex::Autolock lock(mMutex);
+ return mCurrentApi;
+}
+
sp<GraphicBuffer> BufferLayerConsumer::getCurrentBuffer(int* outSlot) const {
Mutex::Autolock lock(mMutex);
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index f473390ea7..a0272b3622 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -138,6 +138,9 @@ public:
// must be called from SF main thread
const Region& getSurfaceDamage() const;
+ // getCurrentApi retrieves the API which queues the current buffer.
+ int getCurrentApi() const;
+
// See GLConsumer::setDefaultBufferSize.
status_t setDefaultBufferSize(uint32_t width, uint32_t height);
@@ -337,6 +340,8 @@ private:
// The portion of this surface that has changed since the previous frame
Region mCurrentSurfaceDamage;
+ int mCurrentApi;
+
uint32_t mDefaultWidth, mDefaultHeight;
// mFilteringEnabled indicates whether the transform matrix is computed for
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index d121a86ead..cf70529b53 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -76,7 +76,8 @@ DisplayDevice::DisplayDevice(
const wp<IBinder>& displayToken,
const sp<DisplaySurface>& displaySurface,
const sp<IGraphicBufferProducer>& producer,
- bool supportWideColor)
+ bool supportWideColor,
+ bool supportHdr)
: lastCompositionHadVisibleLayers(false),
mFlinger(flinger),
mType(type),
@@ -100,6 +101,8 @@ DisplayDevice::DisplayDevice(
mActiveColorMode = HAL_COLOR_MODE_NATIVE;
mDisplayHasWideColor = supportWideColor;
+ mDisplayHasHdr = supportHdr;
+
/*
* Create our display's surface
*/
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 499bf8e6a0..a4706701a8 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -78,7 +78,7 @@ public:
const wp<IBinder>& displayToken,
const sp<DisplaySurface>& displaySurface,
const sp<IGraphicBufferProducer>& producer,
- bool supportWideColor);
+ bool supportWideColor, bool supportHdr);
// clang-format on
~DisplayDevice();
@@ -128,6 +128,7 @@ public:
status_t beginFrame(bool mustRecompose) const;
status_t prepareFrame(HWComposer& hwc);
bool getWideColorSupport() const { return mDisplayHasWideColor; }
+ bool getHdrSupport() const { return mDisplayHasHdr; }
void swapBuffers(HWComposer& hwc) const;
@@ -235,6 +236,7 @@ private:
// Initialized by SurfaceFlinger when the DisplayDevice is created.
// Fed to RenderEngine during composition.
bool mDisplayHasWideColor;
+ bool mDisplayHasHdr;
};
struct DisplayDeviceState {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a91525d8d0..974a261278 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1041,7 +1041,19 @@ status_t SurfaceFlinger::getHdrCapabilities(const sp<IBinder>& display,
std::unique_ptr<HdrCapabilities> capabilities =
getBE().mHwc->getHdrCapabilities(displayDevice->getHwcDisplayId());
if (capabilities) {
- std::swap(*outCapabilities, *capabilities);
+ if (displayDevice->getWideColorSupport() && !displayDevice->getHdrSupport()) {
+ // insert HDR10 as we will force client composition for HDR10
+ // layers
+ std::vector<int32_t> types = capabilities->getSupportedHdrTypes();
+ types.push_back(HAL_HDR_HDR10);
+
+ *outCapabilities = HdrCapabilities(types,
+ capabilities->getDesiredMaxLuminance(),
+ capabilities->getDesiredMaxAverageLuminance(),
+ capabilities->getDesiredMinLuminance());
+ } else {
+ *outCapabilities = std::move(*capabilities);
+ }
} else {
return BAD_VALUE;
}
@@ -1793,7 +1805,7 @@ android_color_mode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) co
}
android_dataspace SurfaceFlinger::bestTargetDataSpace(
- android_dataspace a, android_dataspace b) const {
+ android_dataspace a, android_dataspace b, bool hasHdr) const {
// Only support sRGB and Display-P3 right now.
if (a == HAL_DATASPACE_DISPLAY_P3 || b == HAL_DATASPACE_DISPLAY_P3) {
return HAL_DATASPACE_DISPLAY_P3;
@@ -1804,6 +1816,9 @@ android_dataspace SurfaceFlinger::bestTargetDataSpace(
if (a == HAL_DATASPACE_V0_SCRGB || b == HAL_DATASPACE_V0_SCRGB) {
return HAL_DATASPACE_DISPLAY_P3;
}
+ if (!hasHdr && (a == HAL_DATASPACE_BT2020_PQ || b == HAL_DATASPACE_BT2020_PQ)) {
+ return HAL_DATASPACE_DISPLAY_P3;
+ }
return HAL_DATASPACE_V0_SRGB;
}
@@ -1885,6 +1900,11 @@ void SurfaceFlinger::setUpHWComposer() {
"display %zd: %d", displayId, result);
}
for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+ if (layer->getDataSpace() == HAL_DATASPACE_BT2020_PQ &&
+ !displayDevice->getHdrSupport()) {
+ layer->forceClientComposition(hwcId);
+ }
+
if (layer->getForceClientComposition(hwcId)) {
ALOGV("[%s] Requesting Client composition", layer->getName().string());
layer->setCompositionType(hwcId, HWC2::Composition::Client);
@@ -1899,7 +1919,8 @@ void SurfaceFlinger::setUpHWComposer() {
android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB;
for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
- newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace);
+ newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace,
+ displayDevice->getHdrSupport());
ALOGV("layer: %s, dataspace: %s (%#x), newDataSpace: %s (%#x)",
layer->getName().string(), dataspaceDetails(layer->getDataSpace()).c_str(),
layer->getDataSpace(), dataspaceDetails(newDataSpace).c_str(), newDataSpace);
@@ -2253,9 +2274,19 @@ void SurfaceFlinger::processDisplayChangesLocked() {
useWideColorMode = hasWideColorModes && hasWideColorDisplay;
}
+ bool hasHdrSupport = false;
+ std::unique_ptr<HdrCapabilities> hdrCapabilities =
+ getHwComposer().getHdrCapabilities(state.type);
+ if (hdrCapabilities) {
+ const std::vector<int32_t> types = hdrCapabilities->getSupportedHdrTypes();
+ auto iter = std::find(types.cbegin(), types.cend(), HAL_HDR_HDR10);
+ hasHdrSupport = iter != types.cend();
+ }
+
sp<DisplayDevice> hw =
new DisplayDevice(this, state.type, hwcId, state.isSecure, display,
- dispSurface, producer, useWideColorMode);
+ dispSurface, producer, useWideColorMode,
+ hasHdrSupport);
android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE;
if (useWideColorMode) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 4da0803f67..1349becf13 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -607,7 +607,8 @@ private:
// Given a dataSpace, returns the appropriate color_mode to use
// to display that dataSpace.
android_color_mode pickColorMode(android_dataspace dataSpace) const;
- android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b) const;
+ android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b,
+ bool hasHdr) const;
mat4 computeSaturationMatrix() const;