Strengthen dataspace guarantees in SurfaceFlinger.
Correctly converting from yuv to rgb in RenderEngine requires that the
buffer dataspace is accurate. So, if the dataspace on a layer differs
from the buffer then update the dataspace in the buffer's metadata to be
consistent.
Moreover, some GPU drivers do not perform yuv2rgb in a reasonable way
when the dataspace is UNKNOWN. In that case, reauthor the dataspace to
be sRGB so that there is consistent behavior for an UNKNOWN dataspace.
Finally, some GPU drivers cache gralloc metadata on creation of GPU
resources, which is not compliant with gralloc expectations. So that
vendors have some time to fix the drivers and so that GSI tests pass,
recreate GPU resources when the vendor partition is old and the buffer
is a YCbCr format.
Bug: 247826480
Test: SurfaceControlTest
Change-Id: Iee2641acce3926c826e96c56ececb431868d8598
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index c1920ba..7d16aad 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -171,8 +171,7 @@
mDrawingState.crop.makeInvalid();
mDrawingState.acquireFence = sp<Fence>::make(-1);
mDrawingState.acquireFenceTime = std::make_shared<FenceTime>(mDrawingState.acquireFence);
- mDrawingState.dataspace = ui::Dataspace::UNKNOWN;
- mDrawingState.dataspaceRequested = false;
+ mDrawingState.dataspace = ui::Dataspace::V0_SRGB;
mDrawingState.hdrMetadata.validTypes = 0;
mDrawingState.surfaceDamageRegion = Region::INVALID_REGION;
mDrawingState.cornerRadius = 0.0f;
@@ -208,7 +207,6 @@
mPremultipliedAlpha = !(args.flags & ISurfaceComposerClient::eNonPremultiplied);
mPotentialCursor = args.flags & ISurfaceComposerClient::eCursorWindow;
mProtectedByApp = args.flags & ISurfaceComposerClient::eProtectedByApp;
- mDrawingState.dataspace = ui::Dataspace::V0_SRGB;
mSnapshot->sequence = sequence;
mSnapshot->name = getDebugName();
@@ -3136,7 +3134,6 @@
}
bool Layer::setDataspace(ui::Dataspace dataspace) {
- mDrawingState.dataspaceRequested = true;
if (mDrawingState.dataspace == dataspace) return false;
mDrawingState.dataspace = dataspace;
mDrawingState.modified = true;
@@ -3401,6 +3398,42 @@
mBufferInfo.mTransform = mDrawingState.bufferTransform;
auto lastDataspace = mBufferInfo.mDataspace;
mBufferInfo.mDataspace = translateDataspace(mDrawingState.dataspace);
+ if (mBufferInfo.mBuffer != nullptr) {
+ auto& mapper = GraphicBufferMapper::get();
+ // TODO: We should measure if it's faster to do a blind write if we're on newer api levels
+ // and don't need to possibly remaps buffers.
+ ui::Dataspace dataspace = ui::Dataspace::UNKNOWN;
+ status_t err = OK;
+ {
+ ATRACE_NAME("getDataspace");
+ err = mapper.getDataspace(mBufferInfo.mBuffer->getBuffer()->handle, &dataspace);
+ }
+ if (err != OK || dataspace != mBufferInfo.mDataspace) {
+ {
+ ATRACE_NAME("setDataspace");
+ err = mapper.setDataspace(mBufferInfo.mBuffer->getBuffer()->handle,
+ static_cast<ui::Dataspace>(mBufferInfo.mDataspace));
+ }
+
+ // Some GPU drivers may cache gralloc metadata which means before we composite we need
+ // to upsert RenderEngine's caches. Put in a special workaround to be backwards
+ // compatible with old vendors, with a ticking clock.
+ static const int32_t kVendorVersion =
+ base::GetIntProperty("ro.vndk.version", __ANDROID_API_FUTURE__);
+ if (const auto format =
+ static_cast<aidl::android::hardware::graphics::common::PixelFormat>(
+ mBufferInfo.mBuffer->getPixelFormat());
+ err == OK && kVendorVersion < __ANDROID_API_U__ &&
+ (format ==
+ aidl::android::hardware::graphics::common::PixelFormat::
+ IMPLEMENTATION_DEFINED ||
+ format == aidl::android::hardware::graphics::common::PixelFormat::YCBCR_420_888 ||
+ format == aidl::android::hardware::graphics::common::PixelFormat::YV12 ||
+ format == aidl::android::hardware::graphics::common::PixelFormat::YCBCR_P010)) {
+ mBufferInfo.mBuffer->remapBuffer();
+ }
+ }
+ }
if (lastDataspace != mBufferInfo.mDataspace) {
mFlinger->mHdrLayerInfoChanged = true;
}
@@ -3991,10 +4024,6 @@
}
ui::Dataspace Layer::getDataSpace() const {
- return mDrawingState.dataspaceRequested ? getRequestedDataSpace() : ui::Dataspace::UNKNOWN;
-}
-
-ui::Dataspace Layer::getRequestedDataSpace() const {
return hasBufferOrSidebandStream() ? mBufferInfo.mDataspace : mDrawingState.dataspace;
}
@@ -4002,6 +4031,8 @@
ui::Dataspace updatedDataspace = dataspace;
// translate legacy dataspaces to modern dataspaces
switch (dataspace) {
+ // Treat unknown dataspaces as V0_sRGB
+ case ui::Dataspace::UNKNOWN:
case ui::Dataspace::SRGB:
updatedDataspace = ui::Dataspace::V0_SRGB;
break;