Merge "Manual merge of ag/3738015 because of conflicts. Conflicts are in layers.proto, LayerProtoParser.h and LayerProtoPraser.cpp as master has more fields in layer proto than pi-dev."
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 3d63971..c7b51c8 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -116,7 +116,8 @@
{ "database", "Database", ATRACE_TAG_DATABASE, { } },
{ "network", "Network", ATRACE_TAG_NETWORK, { } },
{ "adb", "ADB", ATRACE_TAG_ADB, { } },
- { "vibrator", "Vibrator", ATRACE_TAG_VIBRATOR, {}},
+ { "vibrator", "Vibrator", ATRACE_TAG_VIBRATOR, { } },
+ { "aidl", "AIDL calls", ATRACE_TAG_AIDL, { } },
{ k_coreServiceCategory, "Core services", 0, { } },
{ k_pdxServiceCategory, "PDX services", 0, { } },
{ "sched", "CPU Scheduling", 0, {
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index fd2fccb..bfd0f16 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1159,6 +1159,10 @@
static void RunDumpsysProto(const std::string& title, int priority,
std::chrono::milliseconds timeout,
std::chrono::milliseconds service_timeout) {
+ if (!ds.IsZipping()) {
+ MYLOGD("Not dumping %s because it's not a zipped bugreport\n", title.c_str());
+ return;
+ }
sp<android::IServiceManager> sm = defaultServiceManager();
Dumpsys dumpsys(sm.get());
Vector<String16> args;
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index 3dfb7e0..29ef648 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -378,8 +378,7 @@
}
if (findAndBumpVersion(hal, version)) {
if (&table != &mImplementationsTable) {
- hal->interfaces[interfaceName].name = interfaceName;
- hal->interfaces[interfaceName].instances.insert(instanceName);
+ hal->insertLegacyInstance(interfaceName, instanceName);
}
hal->transportArch.arch |= arch;
done = true;
@@ -389,17 +388,16 @@
if (done) {
continue; // to next TableEntry
}
- decltype(vintf::ManifestHal::interfaces) interfaces;
- if (&table != &mImplementationsTable) {
- interfaces[interfaceName].name = interfaceName;
- interfaces[interfaceName].instances.insert(instanceName);
- }
- if (!manifest.add(vintf::ManifestHal{
+ vintf::ManifestHal manifestHal{
vintf::HalFormat::HIDL,
std::string{fqName.package()},
{version},
{transport, arch},
- std::move(interfaces)})) {
+ {}};
+ if (&table != &mImplementationsTable) {
+ manifestHal.insertLegacyInstance(interfaceName, instanceName);
+ }
+ if (!manifest.add(std::move(manifestHal))) {
err() << "Warning: cannot add hal '" << fqInstanceName << "'" << std::endl;
}
}
@@ -408,7 +406,7 @@
<< " This is a skeleton " << manifest.type() << " manifest. Notes: " << std::endl
<< INIT_VINTF_NOTES
<< "-->" << std::endl;
- out << vintf::gHalManifestConverter(manifest, vintf::SerializeFlag::HALS_ONLY);
+ out << vintf::gHalManifestConverter(manifest, vintf::SerializeFlag::HALS_NO_FQNAME);
}
std::string ListCommand::INIT_VINTF_NOTES{
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 579f7ec..916576a 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -793,27 +793,17 @@
texCoords[2] = vec2(right, 1.0f - bottom);
texCoords[3] = vec2(right, 1.0f - top);
- //getBE().compositionInfo.re.preMultipliedAlpha = mPremultipliedAlpha;
- //getBE().compositionInfo.re.opaque = isOpaque(s);
- //getBE().compositionInfo.re.disableTexture = false;
- //getBE().compositionInfo.re.color = getColor();
- //getBE().compositionInfo.hwc.dataspace = mCurrentState.dataSpace;
+ getBE().compositionInfo.re.preMultipliedAlpha = mPremultipliedAlpha;
+ getBE().compositionInfo.re.opaque = isOpaque(s);
+ getBE().compositionInfo.re.disableTexture = false;
+ getBE().compositionInfo.re.color = getColor();
+ getBE().compositionInfo.hwc.dataspace = mCurrentState.dataSpace;
- auto& engine(mFlinger->getRenderEngine());
- engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), false /* disableTexture */,
- getColor());
- engine.setSourceDataSpace(mCurrentState.dataSpace);
-
if (mCurrentState.dataSpace == HAL_DATASPACE_BT2020_ITU_PQ &&
mConsumer->getCurrentApi() == NATIVE_WINDOW_API_MEDIA &&
getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102) {
- engine.setSourceY410BT2020(true);
+ getBE().compositionInfo.re.Y410BT2020 = true;
}
-
- engine.drawMesh(getBE().mMesh);
- engine.disableBlending();
-
- engine.setSourceY410BT2020(false);
}
uint32_t BufferLayer::getProducerStickyTransform() const {
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 92d5e21..fe0b30b 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -57,9 +57,6 @@
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
-static bool useTripleFramebuffer = getInt64< ISurfaceFlingerConfigs,
- &ISurfaceFlingerConfigs::maxFrameBufferAcquiredBuffers>(2) >= 3;
-
/*
* Initialize the display to the specified values.
*
@@ -74,72 +71,43 @@
int32_t hwcId,
bool isSecure,
const wp<IBinder>& displayToken,
+ const sp<ANativeWindow>& nativeWindow,
const sp<DisplaySurface>& displaySurface,
- const sp<IGraphicBufferProducer>& producer,
+ std::unique_ptr<RE::Surface> renderSurface,
+ int displayWidth,
+ int displayHeight,
bool supportWideColor,
- bool supportHdr)
+ bool supportHdr,
+ int initialPowerMode)
: lastCompositionHadVisibleLayers(false),
mFlinger(flinger),
mType(type),
mHwcDisplayId(hwcId),
mDisplayToken(displayToken),
+ mNativeWindow(nativeWindow),
mDisplaySurface(displaySurface),
- mSurface{flinger->getRenderEngine().createSurface()},
- mDisplayWidth(),
- mDisplayHeight(),
- mPageFlipCount(),
+ mSurface{std::move(renderSurface)},
+ mDisplayWidth(displayWidth),
+ mDisplayHeight(displayHeight),
+ mPageFlipCount(0),
mIsSecure(isSecure),
mLayerStack(NO_LAYER_STACK),
mOrientation(),
- mPowerMode(HWC_POWER_MODE_OFF),
- mActiveConfig(0)
+ mViewport(Rect::INVALID_RECT),
+ mFrame(Rect::INVALID_RECT),
+ mPowerMode(initialPowerMode),
+ mActiveConfig(0),
+ mActiveColorMode(ColorMode::NATIVE),
+ mDisplayHasWideColor(supportWideColor),
+ mDisplayHasHdr(supportHdr)
{
// clang-format on
- Surface* surface;
- mNativeWindow = surface = new Surface(producer, false);
- ANativeWindow* const window = mNativeWindow.get();
-
- mActiveColorMode = ColorMode::NATIVE;
- mDisplayHasWideColor = supportWideColor;
- mDisplayHasHdr = supportHdr;
-
- /*
- * Create our display's surface
- */
- mSurface->setCritical(mType == DisplayDevice::DISPLAY_PRIMARY);
- mSurface->setAsync(mType >= DisplayDevice::DISPLAY_VIRTUAL);
- mSurface->setNativeWindow(window);
- mDisplayWidth = mSurface->queryWidth();
- mDisplayHeight = mSurface->queryHeight();
-
- // Make sure that composition can never be stalled by a virtual display
- // consumer that isn't processing buffers fast enough. We have to do this
- // in two places:
- // * Here, in case the display is composed entirely by HWC.
- // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the
- // window's swap interval in eglMakeCurrent, so they'll override the
- // interval we set here.
- if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
- window->setSwapInterval(window, 0);
-
- mPageFlipCount = 0;
- mViewport.makeInvalid();
- mFrame.makeInvalid();
-
- // virtual displays are always considered enabled
- mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ?
- HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
// initialize the display orientation transform.
setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
-
- if (useTripleFramebuffer) {
- surface->allocateBuffers();
- }
}
-DisplayDevice::~DisplayDevice() {
-}
+DisplayDevice::~DisplayDevice() = default;
void DisplayDevice::disconnect(HWComposer& hwc) {
if (mHwcDisplayId >= 0) {
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 737971f..fbb0d46 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -77,9 +77,14 @@
int32_t hwcId,
bool isSecure,
const wp<IBinder>& displayToken,
+ const sp<ANativeWindow>& nativeWindow,
const sp<DisplaySurface>& displaySurface,
- const sp<IGraphicBufferProducer>& producer,
- bool supportWideColor, bool supportHdr);
+ std::unique_ptr<RE::Surface> renderSurface,
+ int displayWidth,
+ int displayHeight,
+ bool supportWideColor,
+ bool supportHdr,
+ int initialPowerMode);
// clang-format on
~DisplayDevice();
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index c520f54..b86408e 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -483,6 +483,9 @@
const auto hwcId = displayDevice->getHwcDisplayId();
auto& hwcInfo = getBE().mHwcLayers[hwcId];
+ // Need to program geometry parts
+ getBE().compositionInfo.hwc.skipGeometry = false;
+
// enable this layer
hwcInfo.forceClientComposition = false;
@@ -605,7 +608,7 @@
const uint32_t orientation = transform.getOrientation();
if (orientation & Transform::ROT_INVALID || extremeScaling) {
// we can only handle simple transformation
- hwcInfo.forceClientComposition = true;
+ getBE().mHwcLayers[hwcId].compositionType = HWC2::Composition::Client;
} else {
auto transform = static_cast<HWC2::Transform>(orientation);
hwcInfo.transform = transform;
@@ -613,108 +616,6 @@
}
}
-void Layer::configureHwcLayer(const sp<const DisplayDevice>& displayDevice) {
- ATRACE_CALL();
-
- auto hwcId = displayDevice->getHwcDisplayId();
- auto& hwcInfo = getBE().mHwcLayers[hwcId];
- auto& hwcLayer = hwcInfo.layer;
-
- auto error = (*hwcLayer)->setBlendMode(getBE().compositionInfo.hwc.blendMode);
- ALOGE_IF(error != HWC2::Error::None,
- "[%s] Failed to set blend mode %s:"
- " %s (%d)",
- mName.string(),
- to_string(getBE().compositionInfo.hwc.blendMode).c_str(), to_string(error).c_str(),
- static_cast<int32_t>(error));
-
- error = (*hwcLayer)->setDisplayFrame(getBE().compositionInfo.hwc.displayFrame);
- ALOGE_IF(error != HWC2::Error::None,
- "[%s] Failed to set the display frame [%d, %d, %d, %d] %s (%d)",
- mName.string(),
- getBE().compositionInfo.hwc.displayFrame.left,
- getBE().compositionInfo.hwc.displayFrame.right,
- getBE().compositionInfo.hwc.displayFrame.top,
- getBE().compositionInfo.hwc.displayFrame.bottom,
- to_string(error).c_str(), static_cast<int32_t>(error));
-
-
- error = (*hwcLayer)->setPlaneAlpha(getBE().compositionInfo.hwc.alpha);
- ALOGE_IF(error != HWC2::Error::None,
- "[%s] Failed to set plane alpha %.3f: "
- "%s (%d)",
- mName.string(), getBE().compositionInfo.hwc.alpha,
- to_string(error).c_str(), static_cast<int32_t>(error));
-
- error = (*hwcLayer)->setSourceCrop(getBE().compositionInfo.hwc.sourceCrop);
- ALOGE_IF(error != HWC2::Error::None,
- "[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: %s (%d)",
- mName.string(),
- getBE().compositionInfo.hwc.sourceCrop.left,
- getBE().compositionInfo.hwc.sourceCrop.right,
- getBE().compositionInfo.hwc.sourceCrop.top,
- getBE().compositionInfo.hwc.sourceCrop.bottom,
- to_string(error).c_str(), static_cast<int32_t>(error));
-
- error = (*hwcLayer)->setTransform(getBE().compositionInfo.hwc.transform);
- ALOGE_IF(error != HWC2::Error::None,
- "[%s] Failed to set transform %s: "
- "%s (%d)",
- mName.string(),
- to_string(getBE().compositionInfo.hwc.transform).c_str(), to_string(error).c_str(),
- static_cast<int32_t>(error));
-
- error = (*hwcLayer)->setZOrder(getBE().compositionInfo.hwc.z);
- ALOGE_IF(error != HWC2::Error::None,
- "[%s] Failed to set Z %u: %s (%d)",
- mName.string(), getBE().compositionInfo.hwc.z,
- to_string(error).c_str(), static_cast<int32_t>(error));
-
- error = (*hwcLayer)->setInfo(getBE().compositionInfo.hwc.type, getBE().compositionInfo.hwc.appId);
- ALOGE_IF(error != HWC2::Error::None,
- "[%s] Failed to set info (%d)",
- mName.string(), static_cast<int32_t>(error));
-
- error = (*hwcLayer)->setVisibleRegion(getBE().compositionInfo.hwc.visibleRegion);
- ALOGE_IF(error != HWC2::Error::None,
- "[%s] Failed to set visible region: %s (%d)",
- mName.string(), to_string(error).c_str(), static_cast<int32_t>(error));
-
- error = (*hwcLayer)->setSurfaceDamage(getBE().compositionInfo.hwc.surfaceDamage);
- ALOGE_IF(error != HWC2::Error::None,
- "[%s] Failed to set surface damage: %s (%d)",
- mName.string(), to_string(error).c_str(), static_cast<int32_t>(error));
-
- error = (*hwcLayer)->setCompositionType(getBE().compositionInfo.compositionType);
- ALOGE_IF(error != HWC2::Error::None,
- "[%s] Failed to set composition type: %s (%d)",
- mName.string(), to_string(error).c_str(), static_cast<int32_t>(error));
-
- error = (*hwcLayer)->setDataspace(getBE().compositionInfo.hwc.dataspace);
- ALOGE_IF(error != HWC2::Error::None,
- "[%s] Failed to set dataspace: %s (%d)",
- mName.string(), to_string(error).c_str(), static_cast<int32_t>(error));
-
- error = (*hwcLayer)->setHdrMetadata(getBE().compositionInfo.hwc.hdrMetadata);
- if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) {
- ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(),
- to_string(error).c_str(), static_cast<int32_t>(error));
- }
-
- error = (*hwcLayer)->setColor(getBE().compositionInfo.hwc.color);
- ALOGE_IF(error != HWC2::Error::None,
- "[%s] Failed to set color: %s (%d)",
- mName.string(), to_string(error).c_str(), static_cast<int32_t>(error));
-
- if (getBE().compositionInfo.hwc.fence) {
- error = (*hwcLayer)->setBuffer(getBE().compositionInfo.mBufferSlot,
- getBE().compositionInfo.mBuffer, getBE().compositionInfo.hwc.fence);
- ALOGE_IF(error != HWC2::Error::None,
- "[%s] Failed to set buffer: %s (%d)",
- mName.string(), to_string(error).c_str(), static_cast<int32_t>(error));
- }
-}
-
void Layer::forceClientComposition(int32_t hwcId) {
if (getBE().mHwcLayers.count(hwcId) == 0) {
ALOGE("forceClientComposition: no HWC layer found (%d)", hwcId);
@@ -796,26 +697,12 @@
clearWithOpenGL(renderArea, 0, 0, 0, 0);
}
-void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc) {
- if (getBE().mHwcLayers.count(hwcId) == 0) {
- ALOGE("setCompositionType called without a valid HWC layer");
- return;
- }
- auto& hwcInfo = getBE().mHwcLayers[hwcId];
- auto& hwcLayer = hwcInfo.layer;
- ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", (*hwcLayer)->getId(), to_string(type).c_str(),
- static_cast<int>(callIntoHwc));
- if (hwcInfo.compositionType != type) {
- ALOGV(" actually setting");
- hwcInfo.compositionType = type;
- if (callIntoHwc) {
- auto error = (*hwcLayer)->setCompositionType(type);
- ALOGE_IF(error != HWC2::Error::None,
- "[%s] Failed to set "
- "composition type %s: %s (%d)",
- mName.string(), to_string(type).c_str(), to_string(error).c_str(),
- static_cast<int32_t>(error));
- }
+void Layer::setCompositionType(int32_t /*hwcId*/, HWC2::Composition type, bool /*callIntoHwc*/) {
+ if (getBE().compositionInfo.compositionType != type) {
+ ALOGV("setCompositionType: Changing compositionType from %s to %s",
+ to_string(getBE().compositionInfo.compositionType).c_str(),
+ to_string(type).c_str());
+ getBE().compositionInfo.compositionType = type;
}
}
@@ -825,11 +712,7 @@
// have a HWC counterpart, then it will always be Client
return HWC2::Composition::Client;
}
- if (getBE().mHwcLayers.count(hwcId) == 0) {
- ALOGE("getCompositionType called with an invalid HWC layer");
- return HWC2::Composition::Invalid;
- }
- return getBE().mHwcLayers.at(hwcId).compositionType;
+ return getBE().compositionInfo.compositionType;
}
void Layer::setClearClientTarget(int32_t hwcId, bool clear) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 029f8ac..c1a4dcf 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -309,7 +309,6 @@
virtual void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {}
void setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z);
- void configureHwcLayer(const sp<const DisplayDevice>& displayDevice);
void forceClientComposition(int32_t hwcId);
bool getForceClientComposition(int32_t hwcId);
virtual void setPerFrameData(const sp<const DisplayDevice>& displayDevice) = 0;
diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h
index 06c88a4..fafe165 100644
--- a/services/surfaceflinger/LayerBE.h
+++ b/services/surfaceflinger/LayerBE.h
@@ -66,6 +66,7 @@
LayerBE* layer = nullptr;
struct {
std::shared_ptr<LayerContainer> hwcLayer;
+ bool skipGeometry = true;
int32_t hwid = -1;
sp<Fence> fence;
HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid;
diff --git a/services/surfaceflinger/LayerStats.cpp b/services/surfaceflinger/LayerStats.cpp
index ea2542c..ad1043f 100644
--- a/services/surfaceflinger/LayerStats.cpp
+++ b/services/surfaceflinger/LayerStats.cpp
@@ -56,11 +56,11 @@
}
void LayerStats::traverseLayerTreeStatsLocked(
- const std::vector<const LayerProtoParser::Layer*>& layerTree,
+ std::vector<std::unique_ptr<LayerProtoParser::Layer>> layerTree,
const LayerProtoParser::LayerGlobal* layerGlobal) {
- for (auto layer : layerTree) {
+ for (std::unique_ptr<LayerProtoParser::Layer>& layer : layerTree) {
if (!layer) continue;
- traverseLayerTreeStatsLocked(layer->children, layerGlobal);
+ traverseLayerTreeStatsLocked(std::move(layer->children), layerGlobal);
std::string key =
base::StringPrintf("%s,%s,%s,%s,%s,%s,%s,%s,%s",
destinationLocation(layer->hwcFrame.left,
@@ -71,7 +71,7 @@
layerGlobal->resolution[0], true),
destinationSize(layer->hwcFrame.bottom - layer->hwcFrame.top,
layerGlobal->resolution[1], false),
- layer->type.c_str(), scaleRatioWH(layer).c_str(),
+ layer->type.c_str(), scaleRatioWH(layer.get()).c_str(),
layerTransform(layer->hwcTransform), layer->pixelFormat.c_str(),
layer->dataspace.c_str());
mLayerStatsMap[key]++;
@@ -83,8 +83,7 @@
auto layerGlobal = LayerProtoParser::generateLayerGlobalInfo(layersProto);
auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
std::lock_guard<std::mutex> lock(mMutex);
- traverseLayerTreeStatsLocked(layerTree, &layerGlobal);
- LayerProtoParser::destroyLayerTree(layerTree);
+ traverseLayerTreeStatsLocked(std::move(layerTree), &layerGlobal);
}
void LayerStats::dump(String8& result) {
diff --git a/services/surfaceflinger/LayerStats.h b/services/surfaceflinger/LayerStats.h
index 1924110..9522725 100644
--- a/services/surfaceflinger/LayerStats.h
+++ b/services/surfaceflinger/LayerStats.h
@@ -37,8 +37,9 @@
private:
// Traverse layer tree to get all visible layers' stats
- void traverseLayerTreeStatsLocked(const std::vector<const LayerProtoParser::Layer*>& layerTree,
- const LayerProtoParser::LayerGlobal* layerGlobal);
+ void traverseLayerTreeStatsLocked(
+ std::vector<std::unique_ptr<LayerProtoParser::Layer>> layerTree,
+ const LayerProtoParser::LayerGlobal* layerGlobal);
// Convert layer's top-left position into 8x8 percentage of the display
static const char* destinationLocation(int32_t location, int32_t range, bool isHorizontal);
// Convert layer's size into 8x8 percentage of the display
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index 7a43ea9..6a34981 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -305,15 +305,24 @@
if (needs.hasToneMapping()) {
fs << R"__SHADER__(
- float ToneMapChannel(const float color) {
+ float CalculateY(const vec3 color) {
+ // BT2020 standard uses the unadjusted KR = 0.2627,
+ // KB = 0.0593 luminance interpretation for RGB conversion.
+ return color.r * 0.262700 + color.g * 0.677998 +
+ color.b * 0.059302;
+ }
+ vec3 ToneMap(const vec3 color) {
const float maxLumi = 10000.0;
const float maxMasteringLumi = 1000.0;
const float maxContentLumi = 1000.0;
const float maxInLumi = min(maxMasteringLumi, maxContentLumi);
const float maxOutLumi = 500.0;
+ // Calculate Y value in XYZ color space.
+ float colorY = CalculateY(color);
+
// convert to nits first
- float nits = color * maxLumi;
+ float nits = colorY * maxLumi;
// clamp to max input luminance
nits = clamp(nits, 0.0, maxInLumi);
@@ -360,12 +369,8 @@
}
// convert back to [0.0, 1.0]
- return nits / maxOutLumi;
- }
-
- vec3 ToneMap(const vec3 color) {
- return vec3(ToneMapChannel(color.r), ToneMapChannel(color.g),
- ToneMapChannel(color.b));
+ float targetY = nits / maxOutLumi;
+ return color * (targetY / max(1e-6, colorY));
}
)__SHADER__";
} else {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 4ea7bee..a21b7ea 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -154,6 +154,32 @@
return std::string(value) == "true";
}
+NativeWindowSurface::~NativeWindowSurface() = default;
+
+namespace impl {
+
+class NativeWindowSurface final : public android::NativeWindowSurface {
+public:
+ static std::unique_ptr<android::NativeWindowSurface> create(
+ const sp<IGraphicBufferProducer>& producer) {
+ return std::make_unique<NativeWindowSurface>(producer);
+ }
+
+ explicit NativeWindowSurface(const sp<IGraphicBufferProducer>& producer)
+ : surface(new Surface(producer, false)) {}
+
+ ~NativeWindowSurface() override = default;
+
+private:
+ sp<ANativeWindow> getNativeWindow() const override { return surface; }
+
+ void preallocateBuffers() override { surface->allocateBuffers(); }
+
+ sp<Surface> surface;
+};
+
+} // namespace impl
+
SurfaceFlingerBE::SurfaceFlingerBE()
: mHwcServiceName(getHwcServiceName()),
mRenderEngine(nullptr),
@@ -194,7 +220,8 @@
mNumLayers(0),
mVrFlingerRequestsDisplay(false),
mMainThreadId(std::this_thread::get_id()),
- mCreateBufferQueue(&BufferQueue::createBufferQueue) {}
+ mCreateBufferQueue(&BufferQueue::createBufferQueue),
+ mCreateNativeWindowSurface(&impl::NativeWindowSurface::create) {}
SurfaceFlinger::SurfaceFlinger() : SurfaceFlinger(SkipInitialization) {
ALOGI("SurfaceFlinger is starting");
@@ -1416,7 +1443,13 @@
bool refreshNeeded = handleMessageTransaction();
refreshNeeded |= handleMessageInvalidate();
refreshNeeded |= mRepaintEverything;
+
+ preComposition();
+ rebuildLayerStacks();
+ calculateWorkingSet();
+
if (refreshNeeded) {
+
// Signal a refresh if a transaction modified the window state,
// a new buffer was latched, or if HWC has requested a full
// repaint
@@ -1445,21 +1478,120 @@
return handlePageFlip();
}
+void SurfaceFlinger::calculateWorkingSet() {
+ ATRACE_CALL();
+ ALOGV(__FUNCTION__);
+
+ // build the h/w work list
+ if (CC_UNLIKELY(mGeometryInvalid)) {
+ mGeometryInvalid = false;
+ for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+ sp<const DisplayDevice> displayDevice(mDisplays[dpy]);
+ const auto hwcId = displayDevice->getHwcDisplayId();
+ if (hwcId >= 0) {
+ const Vector<sp<Layer>>& currentLayers(
+ displayDevice->getVisibleLayersSortedByZ());
+ for (size_t i = 0; i < currentLayers.size(); i++) {
+ const auto& layer = currentLayers[i];
+
+ if (!layer->hasHwcLayer(hwcId)) {
+ if (!layer->createHwcLayer(getBE().mHwc.get(), hwcId)) {
+ layer->forceClientComposition(hwcId);
+ continue;
+ }
+ }
+
+ layer->setGeometry(displayDevice, i);
+ if (mDebugDisableHWC || mDebugRegion) {
+ layer->forceClientComposition(hwcId);
+ }
+ }
+ }
+ }
+ }
+ mat4 colorMatrix = mColorMatrix * computeSaturationMatrix() * mDaltonizer();
+
+ // Set the per-frame data
+ for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
+ auto& displayDevice = mDisplays[displayId];
+ const auto hwcId = displayDevice->getHwcDisplayId();
+
+ if (hwcId < 0) {
+ continue;
+ }
+ if (colorMatrix != mPreviousColorMatrix) {
+ status_t result = getBE().mHwc->setColorTransform(hwcId, colorMatrix);
+ ALOGE_IF(result != NO_ERROR, "Failed to set color transform on "
+ "display %zd: %d", displayId, result);
+ }
+ for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+ if ((layer->getDataSpace() == HAL_DATASPACE_BT2020_PQ ||
+ layer->getDataSpace() == HAL_DATASPACE_BT2020_ITU_PQ) &&
+ !displayDevice->getHdrSupport()) {
+ layer->forceClientComposition(hwcId);
+ }
+
+ if (layer->getForceClientComposition(hwcId)) {
+ ALOGV("[%s] Requesting Client composition", layer->getName().string());
+ layer->setCompositionType(hwcId, HWC2::Composition::Client);
+ continue;
+ }
+
+ layer->setPerFrameData(displayDevice);
+ }
+
+ if (hasWideColorDisplay) {
+ ColorMode newColorMode;
+ android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB;
+
+ for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+ 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);
+ }
+ newColorMode = pickColorMode(newDataSpace);
+
+ setActiveColorModeInternal(displayDevice, newColorMode);
+ }
+ }
+
+ mPreviousColorMatrix = colorMatrix;
+ for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
+ auto& displayDevice = mDisplays[displayId];
+ for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+ auto hwcId = displayDevice->getHwcDisplayId();
+ layer->getBE().compositionInfo.compositionType = layer->getCompositionType(hwcId);
+ if (!layer->setHwcLayer(hwcId)) {
+ ALOGV("Need to create HWCLayer for %s", layer->getName().string());
+ }
+ layer->getBE().compositionInfo.hwc.hwid = hwcId;
+ getBE().mCompositionInfo.push_back(layer->getBE().compositionInfo);
+ layer->getBE().compositionInfo.hwc.hwcLayer = nullptr;
+ }
+ }
+}
+
void SurfaceFlinger::handleMessageRefresh() {
ATRACE_CALL();
mRefreshPending = false;
- nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
- preComposition(refreshStartTime);
- rebuildLayerStacks();
- setUpHWComposer();
+
+ beginFrame();
+ for (auto compositionInfo : getBE().mCompositionInfo) {
+ setUpHWComposer(compositionInfo);
+ }
+ prepareFrame();
doDebugFlashRegions();
doTracing("handleRefresh");
logLayerStats();
doComposition();
- postComposition(refreshStartTime);
+ postComposition();
+
+ getBE().mCompositionInfo.clear();
mPreviousPresentFence = getBE().mHwc->getPresentFence(HWC_DISPLAY_PRIMARY);
@@ -1546,14 +1678,14 @@
}
}
-void SurfaceFlinger::preComposition(nsecs_t refreshStartTime)
+void SurfaceFlinger::preComposition()
{
ATRACE_CALL();
ALOGV("preComposition");
bool needExtraInvalidate = false;
mDrawingState.traverseInZOrder([&](Layer* layer) {
- if (layer->onPreComposition(refreshStartTime)) {
+ if (layer->onPreComposition(mRefreshStartTime)) {
needExtraInvalidate = true;
}
});
@@ -1622,7 +1754,7 @@
getBE().mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
}
-void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
+void SurfaceFlinger::postComposition()
{
ATRACE_CALL();
ALOGV("postComposition");
@@ -1654,11 +1786,11 @@
nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0);
nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod();
- // We use the refreshStartTime which might be sampled a little later than
+ // We use the mRefreshStartTime which might be sampled a little later than
// when we started doing work for this frame, but that should be okay
// since updateCompositorTiming has snapping logic.
updateCompositorTiming(
- vsyncPhase, vsyncInterval, refreshStartTime, presentFenceTime);
+ vsyncPhase, vsyncInterval, mRefreshStartTime, presentFenceTime);
CompositorTiming compositorTiming;
{
std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock);
@@ -1756,17 +1888,21 @@
if (!drawRegion.isEmpty()) {
layersSortedByZ.add(layer);
} else {
- // Clear out the HWC layer if this layer was
- // previously visible, but no longer is
+ if (layer->hasHwcLayer(displayDevice->getHwcDisplayId())) {
+ // Clear out the HWC layer if this layer was
+ // previously visible, but no longer is
+ hwcLayerDestroyed = layer->destroyHwcLayer(
+ displayDevice->getHwcDisplayId());
+ }
+ }
+ } else {
+ if (layer->hasHwcLayer(displayDevice->getHwcDisplayId())) {
+ // WM changes displayDevice->layerStack upon sleep/awake.
+ // Here we make sure we delete the HWC layers even if
+ // WM changed their layer stack.
hwcLayerDestroyed = layer->destroyHwcLayer(
displayDevice->getHwcDisplayId());
}
- } else {
- // WM changes displayDevice->layerStack upon sleep/awake.
- // Here we make sure we delete the HWC layers even if
- // WM changed their layer stack.
- hwcLayerDestroyed = layer->destroyHwcLayer(
- displayDevice->getHwcDisplayId());
}
// If a layer is not going to get a release fence because
@@ -1861,9 +1997,123 @@
return HAL_DATASPACE_V0_SRGB;
}
-void SurfaceFlinger::setUpHWComposer() {
- ATRACE_CALL();
- ALOGV("setUpHWComposer");
+void SurfaceFlinger::configureSidebandComposition(const CompositionInfo& compositionInfo) const
+{
+ HWC2::Error error;
+ LOG_ALWAYS_FATAL_IF(compositionInfo.hwc.sidebandStream == nullptr,
+ "CompositionType is sideband, but sideband stream is nullptr");
+ error = (*compositionInfo.hwc.hwcLayer)
+ ->setSidebandStream(compositionInfo.hwc.sidebandStream->handle());
+ if (error != HWC2::Error::None) {
+ ALOGE("[SF] Failed to set sideband stream %p: %s (%d)",
+ compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(),
+ static_cast<int32_t>(error));
+ }
+}
+
+void SurfaceFlinger::configureHwcCommonData(const CompositionInfo& compositionInfo) const
+{
+ HWC2::Error error;
+
+ if (!compositionInfo.hwc.skipGeometry) {
+ error = (*compositionInfo.hwc.hwcLayer)->setBlendMode(compositionInfo.hwc.blendMode);
+ ALOGE_IF(error != HWC2::Error::None,
+ "[SF] Failed to set blend mode %s:"
+ " %s (%d)",
+ to_string(compositionInfo.hwc.blendMode).c_str(), to_string(error).c_str(),
+ static_cast<int32_t>(error));
+
+ error = (*compositionInfo.hwc.hwcLayer)->setDisplayFrame(compositionInfo.hwc.displayFrame);
+ ALOGE_IF(error != HWC2::Error::None,
+ "[SF] Failed to set the display frame [%d, %d, %d, %d] %s (%d)",
+ compositionInfo.hwc.displayFrame.left,
+ compositionInfo.hwc.displayFrame.right,
+ compositionInfo.hwc.displayFrame.top,
+ compositionInfo.hwc.displayFrame.bottom,
+ to_string(error).c_str(), static_cast<int32_t>(error));
+
+ error = (*compositionInfo.hwc.hwcLayer)->setSourceCrop(compositionInfo.hwc.sourceCrop);
+ ALOGE_IF(error != HWC2::Error::None,
+ "[SF] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: %s (%d)",
+ compositionInfo.hwc.sourceCrop.left,
+ compositionInfo.hwc.sourceCrop.right,
+ compositionInfo.hwc.sourceCrop.top,
+ compositionInfo.hwc.sourceCrop.bottom,
+ to_string(error).c_str(), static_cast<int32_t>(error));
+
+ error = (*compositionInfo.hwc.hwcLayer)->setPlaneAlpha(compositionInfo.hwc.alpha);
+ ALOGE_IF(error != HWC2::Error::None,
+ "[SF] Failed to set plane alpha %.3f: "
+ "%s (%d)",
+ compositionInfo.hwc.alpha,
+ to_string(error).c_str(), static_cast<int32_t>(error));
+
+
+ error = (*compositionInfo.hwc.hwcLayer)->setZOrder(compositionInfo.hwc.z);
+ ALOGE_IF(error != HWC2::Error::None,
+ "[SF] Failed to set Z %u: %s (%d)",
+ compositionInfo.hwc.z,
+ to_string(error).c_str(), static_cast<int32_t>(error));
+
+ error = (*compositionInfo.hwc.hwcLayer)
+ ->setInfo(compositionInfo.hwc.type, compositionInfo.hwc.appId);
+ ALOGE_IF(error != HWC2::Error::None,
+ "[SF] Failed to set info (%d)",
+ static_cast<int32_t>(error));
+
+ error = (*compositionInfo.hwc.hwcLayer)->setTransform(compositionInfo.hwc.transform);
+ ALOGE_IF(error != HWC2::Error::None,
+ "[SF] Failed to set transform %s: "
+ "%s (%d)",
+ to_string(compositionInfo.hwc.transform).c_str(), to_string(error).c_str(),
+ static_cast<int32_t>(error));
+ }
+
+ error = (*compositionInfo.hwc.hwcLayer)->setCompositionType(compositionInfo.compositionType);
+ ALOGE_IF(error != HWC2::Error::None,
+ "[SF] Failed to set composition type: %s (%d)",
+ to_string(error).c_str(), static_cast<int32_t>(error));
+
+ error = (*compositionInfo.hwc.hwcLayer)->setDataspace(compositionInfo.hwc.dataspace);
+ ALOGE_IF(error != HWC2::Error::None,
+ "[SF] Failed to set dataspace: %s (%d)",
+ to_string(error).c_str(), static_cast<int32_t>(error));
+
+ error = (*compositionInfo.hwc.hwcLayer)->setHdrMetadata(compositionInfo.hwc.hdrMetadata);
+ ALOGE_IF(error != HWC2::Error::None && error != HWC2::Error::Unsupported,
+ "[SF] Failed to set hdrMetadata: %s (%d)",
+ to_string(error).c_str(), static_cast<int32_t>(error));
+
+ error = (*compositionInfo.hwc.hwcLayer)->setColor(compositionInfo.hwc.color);
+ ALOGE_IF(error != HWC2::Error::None,
+ "[SF] Failed to set color: %s (%d)",
+ to_string(error).c_str(), static_cast<int32_t>(error));
+
+ error = (*compositionInfo.hwc.hwcLayer)->setVisibleRegion(compositionInfo.hwc.visibleRegion);
+ ALOGE_IF(error != HWC2::Error::None,
+ "[SF] Failed to set visible region: %s (%d)",
+ to_string(error).c_str(), static_cast<int32_t>(error));
+}
+
+void SurfaceFlinger::configureDeviceComposition(const CompositionInfo& compositionInfo) const
+{
+ HWC2::Error error;
+
+ error = (*compositionInfo.hwc.hwcLayer)->setSurfaceDamage(compositionInfo.hwc.surfaceDamage);
+ ALOGE_IF(error != HWC2::Error::None,
+ "[SF] Failed to set surface damage: %s (%d)",
+ to_string(error).c_str(), static_cast<int32_t>(error));
+
+ error = (*compositionInfo.hwc.hwcLayer)->setBuffer(compositionInfo.mBufferSlot,
+ compositionInfo.mBuffer, compositionInfo.hwc.fence);
+ ALOGE_IF(error != HWC2::Error::None,
+ "[SF] Failed to set buffer: %s (%d)",
+ to_string(error).c_str(), static_cast<int32_t>(error));
+}
+
+void SurfaceFlinger::beginFrame()
+{
+ mRefreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
bool dirty = !mDisplays[dpy]->getDirtyRegion(false).isEmpty();
@@ -1893,97 +2143,10 @@
mDisplays[dpy]->lastCompositionHadVisibleLayers = !empty;
}
}
+}
- // build the h/w work list
- if (CC_UNLIKELY(mGeometryInvalid)) {
- mGeometryInvalid = false;
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- sp<const DisplayDevice> displayDevice(mDisplays[dpy]);
- const auto hwcId = displayDevice->getHwcDisplayId();
- if (hwcId >= 0) {
- const Vector<sp<Layer>>& currentLayers(
- displayDevice->getVisibleLayersSortedByZ());
- for (size_t i = 0; i < currentLayers.size(); i++) {
- const auto& layer = currentLayers[i];
- if (!layer->hasHwcLayer(hwcId)) {
- if (!layer->createHwcLayer(getBE().mHwc.get(), hwcId)) {
- layer->forceClientComposition(hwcId);
- continue;
- }
- }
-
- layer->setGeometry(displayDevice, i);
- if (mDebugDisableHWC || mDebugRegion) {
- layer->forceClientComposition(hwcId);
- }
- }
- }
- }
- }
-
-
- mat4 colorMatrix = mColorMatrix * computeSaturationMatrix() * mDaltonizer();
-
- // Set the per-frame data
- for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
- auto& displayDevice = mDisplays[displayId];
- const auto hwcId = displayDevice->getHwcDisplayId();
-
- if (hwcId < 0) {
- continue;
- }
- if (colorMatrix != mPreviousColorMatrix) {
- status_t result = getBE().mHwc->setColorTransform(hwcId, colorMatrix);
- ALOGE_IF(result != NO_ERROR, "Failed to set color transform on "
- "display %zd: %d", displayId, result);
- }
- for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
- if ((layer->getDataSpace() == HAL_DATASPACE_BT2020_PQ ||
- layer->getDataSpace() == HAL_DATASPACE_BT2020_ITU_PQ) &&
- !displayDevice->getHdrSupport()) {
- layer->forceClientComposition(hwcId);
- }
-
- if (layer->getForceClientComposition(hwcId)) {
- ALOGV("[%s] Requesting Client composition", layer->getName().string());
- layer->setCompositionType(hwcId, HWC2::Composition::Client);
- continue;
- }
-
- layer->setPerFrameData(displayDevice);
- }
-
- if (hasWideColorDisplay) {
- ColorMode newColorMode;
- android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB;
-
- for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
- 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);
- }
- newColorMode = pickColorMode(newDataSpace);
-
- setActiveColorModeInternal(displayDevice, newColorMode);
- }
- }
-
- mPreviousColorMatrix = colorMatrix;
-
- for (size_t dpy = 0; dpy < mDisplays.size(); dpy++) {
- sp<const DisplayDevice> displayDevice(mDisplays[dpy]);
- const auto hwcId = displayDevice->getHwcDisplayId();
- if (hwcId >= 0) {
- const Vector<sp<Layer>>& currentLayers(
- displayDevice->getVisibleLayersSortedByZ());
- for (auto& layer : currentLayers) {
- layer->configureHwcLayer(displayDevice);
- }
- }
- }
-
+void SurfaceFlinger::prepareFrame()
+{
for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
auto& displayDevice = mDisplays[displayId];
if (!displayDevice->isDisplayOn()) {
@@ -1996,6 +2159,32 @@
}
}
+void SurfaceFlinger::setUpHWComposer(const CompositionInfo& compositionInfo) {
+ ATRACE_CALL();
+ ALOGV("setUpHWComposer");
+
+ switch (compositionInfo.compositionType)
+ {
+ case HWC2::Composition::Invalid:
+ case HWC2::Composition::Client:
+ case HWC2::Composition::Cursor:
+ break;
+
+ case HWC2::Composition::Sideband:
+ configureSidebandComposition(compositionInfo);
+ break;
+
+ case HWC2::Composition::SolidColor:
+ configureHwcCommonData(compositionInfo);
+ break;
+
+ case HWC2::Composition::Device:
+ configureHwcCommonData(compositionInfo);
+ configureDeviceComposition(compositionInfo);
+ break;
+ }
+}
+
void SurfaceFlinger::doComposition() {
ATRACE_CALL();
ALOGV("doComposition");
@@ -2113,7 +2302,7 @@
}
DisplayDevice::DisplayType SurfaceFlinger::determineDisplayType(hwc2_display_t display,
- HWC2::Connection connection) const {
+ HWC2::Connection connection) const {
// Figure out whether the event is for the primary display or an
// external display by matching the Hwc display id against one for a
// connected display. If we did not find a match, we then check what
@@ -2182,6 +2371,84 @@
mPendingHotplugEvents.clear();
}
+sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
+ const wp<IBinder>& display, int hwcId, const DisplayDeviceState& state,
+ const sp<DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) {
+ bool hasWideColorSupport = false;
+ if (hasWideColorDisplay) {
+ std::vector<ColorMode> modes = getHwComposer().getColorModes(state.type);
+ for (ColorMode colorMode : modes) {
+ switch (colorMode) {
+ case ColorMode::DISPLAY_P3:
+ case ColorMode::ADOBE_RGB:
+ case ColorMode::DCI_P3:
+ hasWideColorSupport = true;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ 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();
+ }
+
+ auto nativeWindowSurface = mCreateNativeWindowSurface(producer);
+ auto nativeWindow = nativeWindowSurface->getNativeWindow();
+
+ /*
+ * Create our display's surface
+ */
+ std::unique_ptr<RE::Surface> renderSurface = getRenderEngine().createSurface();
+ renderSurface->setCritical(state.type == DisplayDevice::DISPLAY_PRIMARY);
+ renderSurface->setAsync(state.type >= DisplayDevice::DISPLAY_VIRTUAL);
+ renderSurface->setNativeWindow(nativeWindow.get());
+ const int displayWidth = renderSurface->queryWidth();
+ const int displayHeight = renderSurface->queryHeight();
+
+ // Make sure that composition can never be stalled by a virtual display
+ // consumer that isn't processing buffers fast enough. We have to do this
+ // in two places:
+ // * Here, in case the display is composed entirely by HWC.
+ // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the
+ // window's swap interval in eglMakeCurrent, so they'll override the
+ // interval we set here.
+ if (state.type >= DisplayDevice::DISPLAY_VIRTUAL) {
+ nativeWindow->setSwapInterval(nativeWindow.get(), 0);
+ }
+
+ // virtual displays are always considered enabled
+ auto initialPowerMode = (state.type >= DisplayDevice::DISPLAY_VIRTUAL) ? HWC_POWER_MODE_NORMAL
+ : HWC_POWER_MODE_OFF;
+
+ sp<DisplayDevice> hw =
+ new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow,
+ dispSurface, std::move(renderSurface), displayWidth, displayHeight,
+ hasWideColorSupport, hasHdrSupport, initialPowerMode);
+
+ if (maxFrameBufferAcquiredBuffers >= 3) {
+ nativeWindowSurface->preallocateBuffers();
+ }
+
+ ColorMode defaultColorMode = ColorMode::NATIVE;
+ if (hasWideColorSupport) {
+ defaultColorMode = ColorMode::SRGB;
+ }
+ setActiveColorModeInternal(hw, defaultColorMode);
+ hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN);
+ hw->setLayerStack(state.layerStack);
+ hw->setProjection(state.orientation, state.viewport, state.frame);
+ hw->setDisplayName(state.displayName);
+
+ return hw;
+}
+
void SurfaceFlinger::processDisplayChangesLocked() {
// here we take advantage of Vector's copy-on-write semantics to
// improve performance by skipping the transaction entirely when
@@ -2304,50 +2571,10 @@
}
const wp<IBinder>& display(curr.keyAt(i));
-
if (dispSurface != nullptr) {
- bool hasWideColorSupport = false;
- if (hasWideColorDisplay) {
- std::vector<ColorMode> modes =
- getHwComposer().getColorModes(state.type);
- for (ColorMode colorMode : modes) {
- switch (colorMode) {
- case ColorMode::DISPLAY_P3:
- case ColorMode::ADOBE_RGB:
- case ColorMode::DCI_P3:
- hasWideColorSupport = true;
- break;
- default:
- break;
- }
- }
- }
-
- 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, hasWideColorSupport,
- hasHdrSupport);
-
- ColorMode defaultColorMode = ColorMode::NATIVE;
- if (hasWideColorSupport) {
- defaultColorMode = ColorMode::SRGB;
- }
- setActiveColorModeInternal(hw, defaultColorMode);
- hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN);
- hw->setLayerStack(state.layerStack);
- hw->setProjection(state.orientation, state.viewport, state.frame);
- hw->setDisplayName(state.displayName);
-
- mDisplays.add(display, hw);
+ mDisplays.add(display,
+ setupNewDisplayDeviceInternal(display, hwcId, state, dispSurface,
+ producer));
if (!state.isVirtualDisplay()) {
mEventThread->onHotplugReceived(state.type, true);
}
@@ -4062,7 +4289,7 @@
LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current);
auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
- result.append(LayerProtoParser::layersToString(layerTree).c_str());
+ result.append(LayerProtoParser::layersToString(std::move(layerTree)).c_str());
/*
* Dump Display state
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 3b80756..77efa54 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -121,6 +121,19 @@
eTransactionMask = 0x07
};
+// A thin interface to abstract creating instances of Surface (gui/Surface.h) to
+// use as a NativeWindow.
+class NativeWindowSurface {
+public:
+ virtual ~NativeWindowSurface();
+
+ // Gets the NativeWindow to use for the surface.
+ virtual sp<ANativeWindow> getNativeWindow() const = 0;
+
+ // Indicates that the surface should allocate its buffers now.
+ virtual void preallocateBuffers() = 0;
+};
+
class SurfaceFlingerBE
{
public:
@@ -201,6 +214,8 @@
// use to differentiate callbacks from different hardware composer
// instances. Each hardware composer instance gets a different sequence id.
int32_t mComposerSequenceId;
+
+ std::vector<CompositionInfo> mCompositionInfo;
};
@@ -613,8 +628,8 @@
void computeVisibleRegions(const sp<const DisplayDevice>& displayDevice,
Region& dirtyRegion, Region& opaqueRegion);
- void preComposition(nsecs_t refreshStartTime);
- void postComposition(nsecs_t refreshStartTime);
+ void preComposition();
+ void postComposition();
void updateCompositorTiming(
nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime,
std::shared_ptr<FenceTime>& presentFenceTime);
@@ -631,7 +646,19 @@
mat4 computeSaturationMatrix() const;
- void setUpHWComposer();
+ void calculateWorkingSet();
+ /*
+ * beginFrame - This function handles any pre-frame processing that needs to be
+ * prior to any CompositionInfo handling and is not dependent on data in
+ * CompositionInfo
+ */
+ void beginFrame();
+ /* prepareFrame - This function will call into the DisplayDevice to prepare a
+ * frame after CompositionInfo has been programmed. This provides a mechanism
+ * to prepare the hardware composer
+ */
+ void prepareFrame();
+ void setUpHWComposer(const CompositionInfo& compositionInfo);
void doComposition();
void doDebugFlashRegions();
void doTracing(const char* where);
@@ -650,6 +677,10 @@
*/
DisplayDevice::DisplayType determineDisplayType(hwc2_display_t display,
HWC2::Connection connection) const;
+ sp<DisplayDevice> setupNewDisplayDeviceInternal(const wp<IBinder>& display, int hwcId,
+ const DisplayDeviceState& state,
+ const sp<DisplaySurface>& dispSurface,
+ const sp<IGraphicBufferProducer>& producer);
void processDisplayChangesLocked();
void processDisplayHotplugEventsLocked();
@@ -737,6 +768,11 @@
// access must be protected by mInvalidateLock
volatile int32_t mRepaintEverything;
+ // helper methods
+ void configureHwcCommonData(const CompositionInfo& compositionInfo) const;
+ void configureDeviceComposition(const CompositionInfo& compositionInfo) const;
+ void configureSidebandComposition(const CompositionInfo& compositionInfo) const;
+
// constant members (no synchronization needed for access)
nsecs_t mBootTime;
bool mGpuToCpuSupported;
@@ -804,6 +840,7 @@
Mutex mHWVsyncLock;
bool mPrimaryHWVsyncEnabled;
bool mHWVsyncAvailable;
+ nsecs_t mRefreshStartTime;
std::atomic<bool> mRefreshPending{false};
@@ -843,6 +880,10 @@
bool /* consumerIsSurfaceFlinger */)>;
CreateBufferQueueFunction mCreateBufferQueue;
+ using CreateNativeWindowSurfaceFunction =
+ std::function<std::unique_ptr<NativeWindowSurface>(const sp<IGraphicBufferProducer>&)>;
+ CreateNativeWindowSurfaceFunction mCreateNativeWindowSurface;
+
SurfaceFlingerBE mBE;
};
}; // namespace android
diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
index e4545e4..b10e07b 100644
--- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp
+++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#include <android-base/stringprintf.h>
#include <layerproto/LayerProtoParser.h>
#include <ui/DebugUtils.h>
@@ -24,7 +23,7 @@
namespace android {
namespace surfaceflinger {
-bool sortLayers(const LayerProtoParser::Layer* lhs, const LayerProtoParser::Layer* rhs) {
+bool sortLayers(LayerProtoParser::Layer* lhs, const LayerProtoParser::Layer* rhs) {
uint32_t ls = lhs->layerStack;
uint32_t rs = rhs->layerStack;
if (ls != rs) return ls < rs;
@@ -38,33 +37,30 @@
return lhs->id < rhs->id;
}
+bool sortLayerUniquePtrs(const std::unique_ptr<LayerProtoParser::Layer>& lhs,
+ const std::unique_ptr<LayerProtoParser::Layer>& rhs) {
+ return sortLayers(lhs.get(), rhs.get());
+}
+
const LayerProtoParser::LayerGlobal LayerProtoParser::generateLayerGlobalInfo(
const LayersProto& layersProto) {
return {{layersProto.resolution().w(), layersProto.resolution().h()}};
}
-void LayerProtoParser::destroyLayerTree(
- const std::vector<const LayerProtoParser::Layer*>& layerTree) {
- for (auto layer : layerTree) {
- destroyLayerTree(layer->children);
- delete layer;
- }
-}
-
-std::vector<const LayerProtoParser::Layer*> LayerProtoParser::generateLayerTree(
+std::vector<std::unique_ptr<LayerProtoParser::Layer>> LayerProtoParser::generateLayerTree(
const LayersProto& layersProto) {
- auto layerMap = generateMap(layersProto);
+ std::unordered_map<int32_t, LayerProtoParser::Layer*> layerMap = generateMap(layersProto);
+ std::vector<std::unique_ptr<LayerProtoParser::Layer>> layers;
- std::vector<const Layer*> layers;
- std::for_each(layerMap.begin(), layerMap.end(),
- [&](const std::pair<const int32_t, Layer*>& ref) {
- if (ref.second->parent == nullptr) {
- // only save top level layers
- layers.push_back(ref.second);
- }
- });
+ for (std::pair<int32_t, Layer*> kv : layerMap) {
+ if (kv.second->parent == nullptr) {
+ // Make unique_ptr for top level layers since they are not children. This ensures there
+ // will only be one unique_ptr made for each layer.
+ layers.push_back(std::unique_ptr<Layer>(kv.second));
+ }
+ }
- std::sort(layers.begin(), layers.end(), sortLayers);
+ std::sort(layers.begin(), layers.end(), sortLayerUniquePtrs);
return layers;
}
@@ -183,63 +179,61 @@
for (int i = 0; i < layerProto.children_size(); i++) {
if (layerMap.count(layerProto.children(i)) > 0) {
- auto childLayer = layerMap[layerProto.children(i)];
- currLayer->children.push_back(childLayer);
+ // Only make unique_ptrs for children since they are guaranteed to be unique, only one
+ // parent per child. This ensures there will only be one unique_ptr made for each layer.
+ currLayer->children.push_back(std::unique_ptr<Layer>(layerMap[layerProto.children(i)]));
}
}
for (int i = 0; i < layerProto.relatives_size(); i++) {
if (layerMap.count(layerProto.relatives(i)) > 0) {
- auto relativeLayer = layerMap[layerProto.relatives(i)];
- currLayer->relatives.push_back(relativeLayer);
+ currLayer->relatives.push_back(layerMap[layerProto.relatives(i)]);
}
}
if (layerProto.has_parent()) {
if (layerMap.count(layerProto.parent()) > 0) {
- auto parentLayer = layerMap[layerProto.parent()];
- currLayer->parent = parentLayer;
+ currLayer->parent = layerMap[layerProto.parent()];
}
}
if (layerProto.has_z_order_relative_of()) {
if (layerMap.count(layerProto.z_order_relative_of()) > 0) {
- auto relativeLayer = layerMap[layerProto.z_order_relative_of()];
- currLayer->zOrderRelativeOf = relativeLayer;
+ currLayer->zOrderRelativeOf = layerMap[layerProto.z_order_relative_of()];
}
}
}
std::string LayerProtoParser::layersToString(
- const std::vector<const LayerProtoParser::Layer*> layers) {
+ std::vector<std::unique_ptr<LayerProtoParser::Layer>> layers) {
std::string result;
- for (const LayerProtoParser::Layer* layer : layers) {
+ for (std::unique_ptr<LayerProtoParser::Layer>& layer : layers) {
if (layer->zOrderRelativeOf != nullptr) {
continue;
}
- result.append(layerToString(layer).c_str());
+ result.append(layerToString(layer.get()).c_str());
}
return result;
}
-std::string LayerProtoParser::layerToString(const LayerProtoParser::Layer* layer) {
+std::string LayerProtoParser::layerToString(LayerProtoParser::Layer* layer) {
std::string result;
- std::vector<const Layer*> traverse(layer->relatives);
- for (const LayerProtoParser::Layer* child : layer->children) {
+ std::vector<Layer*> traverse(layer->relatives);
+ for (std::unique_ptr<LayerProtoParser::Layer>& child : layer->children) {
if (child->zOrderRelativeOf != nullptr) {
continue;
}
- traverse.push_back(child);
+ traverse.push_back(child.get());
}
std::sort(traverse.begin(), traverse.end(), sortLayers);
size_t i = 0;
for (; i < traverse.size(); i++) {
- const auto& relative = traverse[i];
+ auto& relative = traverse[i];
if (relative->z >= 0) {
break;
}
@@ -248,7 +242,7 @@
result.append(layer->to_string().c_str());
result.append("\n");
for (; i < traverse.size(); i++) {
- const auto& relative = traverse[i];
+ auto& relative = traverse[i];
result.append(layerToString(relative).c_str());
}
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
index 4466326..fd893da 100644
--- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
@@ -19,6 +19,7 @@
#include <math/vec4.h>
+#include <memory>
#include <unordered_map>
#include <vector>
@@ -79,8 +80,8 @@
public:
int32_t id;
std::string name;
- std::vector<const Layer*> children;
- std::vector<const Layer*> relatives;
+ std::vector<std::unique_ptr<Layer>> children;
+ std::vector<Layer*> relatives;
std::string type;
LayerProtoParser::Region transparentRegion;
LayerProtoParser::Region visibleRegion;
@@ -121,9 +122,8 @@
};
static const LayerGlobal generateLayerGlobalInfo(const LayersProto& layersProto);
- static std::vector<const Layer*> generateLayerTree(const LayersProto& layersProto);
- static void destroyLayerTree(const std::vector<const LayerProtoParser::Layer*>& layerTree);
- static std::string layersToString(const std::vector<const LayerProtoParser::Layer*> layers);
+ static std::vector<std::unique_ptr<Layer>> generateLayerTree(const LayersProto& layersProto);
+ static std::string layersToString(std::vector<std::unique_ptr<LayerProtoParser::Layer>> layers);
private:
static std::unordered_map<int32_t, Layer*> generateMap(const LayersProto& layersProto);
@@ -137,7 +137,7 @@
static void updateChildrenAndRelative(const LayerProto& layerProto,
std::unordered_map<int32_t, Layer*>& layerMap);
- static std::string layerToString(const LayerProtoParser::Layer* layer);
+ static std::string layerToString(LayerProtoParser::Layer* layer);
};
} // namespace surfaceflinger
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index 7d3da32..7523399 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -33,6 +33,7 @@
"libEGL",
"libGLESv2",
"libgui",
+ "liblayers_proto",
"liblog",
"libprotobuf-cpp-full",
"libui",
diff --git a/services/surfaceflinger/tests/Stress_test.cpp b/services/surfaceflinger/tests/Stress_test.cpp
index 33dd2f5..4577153 100644
--- a/services/surfaceflinger/tests/Stress_test.cpp
+++ b/services/surfaceflinger/tests/Stress_test.cpp
@@ -22,7 +22,7 @@
#include <thread>
#include <functional>
-
+#include <layerproto/LayerProtoParser.h>
namespace android {
@@ -47,4 +47,66 @@
}
}
+surfaceflinger::LayersProto generateLayerProto() {
+ surfaceflinger::LayersProto layersProto;
+ std::array<surfaceflinger::LayerProto*, 10> layers = {};
+ for (size_t i = 0; i < layers.size(); ++i) {
+ layers[i] = layersProto.add_layers();
+ layers[i]->set_id(i);
+ }
+
+ layers[0]->add_children(1);
+ layers[1]->set_parent(0);
+ layers[0]->add_children(2);
+ layers[2]->set_parent(0);
+ layers[0]->add_children(3);
+ layers[3]->set_parent(0);
+ layers[2]->add_children(4);
+ layers[4]->set_parent(2);
+ layers[3]->add_children(5);
+ layers[5]->set_parent(3);
+ layers[5]->add_children(6);
+ layers[6]->set_parent(5);
+ layers[5]->add_children(7);
+ layers[7]->set_parent(5);
+ layers[6]->add_children(8);
+ layers[8]->set_parent(6);
+
+ layers[4]->set_z_order_relative_of(3);
+ layers[3]->add_relatives(4);
+ layers[8]->set_z_order_relative_of(9);
+ layers[9]->add_relatives(8);
+ layers[3]->set_z_order_relative_of(1);
+ layers[1]->add_relatives(3);
+
+/* ----------------------------
+ * - 0 - - 9 -
+ * / | \
+ * 1 2 3(1)
+ * | |
+ * 4(3) 5
+ * / \
+ * 6 7
+ * |
+ * 8(9)
+ * -------------------------- */
+
+ return layersProto;
+}
+
+TEST(LayerProtoStress, mem_info) {
+ std::string cmd = "dumpsys meminfo ";
+ cmd += std::to_string(getpid());
+ system(cmd.c_str());
+ for (int i = 0; i < 100000; i++) {
+ surfaceflinger::LayersProto layersProto = generateLayerProto();
+ auto layerTree = surfaceflinger::LayerProtoParser::generateLayerTree(layersProto);
+ // Allow some layerTrees to just fall out of scope (instead of std::move)
+ if (i % 2) {
+ surfaceflinger::LayerProtoParser::layersToString(std::move(layerTree));
+ }
+ }
+ system(cmd.c_str());
+}
+
}
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 36bc80f..8ffc5ad 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -28,6 +28,7 @@
"MockGraphicBufferProducer.cpp",
"MockMessageQueue.cpp",
"MockNativeWindow.cpp",
+ "MockNativeWindowSurface.cpp",
"MockRenderEngine.cpp",
"MockSurfaceInterceptor.cpp",
],
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 48b9e92..c048c58 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -21,12 +21,19 @@
#include <gtest/gtest.h>
#include <log/log.h>
+#include "system/window.h"
#include "MockComposer.h"
+#include "MockDisplaySurface.h"
+#include "MockEventControlThread.h"
#include "MockEventThread.h"
#include "MockGraphicBufferConsumer.h"
#include "MockGraphicBufferProducer.h"
+#include "MockMessageQueue.h"
+#include "MockNativeWindow.h"
+#include "MockNativeWindowSurface.h"
#include "MockRenderEngine.h"
+#include "MockSurfaceInterceptor.h"
#include "TestableSurfaceFlinger.h"
namespace android {
@@ -39,41 +46,119 @@
using testing::Return;
using testing::SetArgPointee;
+using android::hardware::graphics::common::V1_0::ColorMode;
using android::hardware::graphics::common::V1_0::Hdr;
using android::Hwc2::Error;
using android::Hwc2::IComposer;
using android::Hwc2::IComposerClient;
using HWC2Display = TestableSurfaceFlinger::HWC2Display;
+using HotplugEvent = TestableSurfaceFlinger::HotplugEvent;
constexpr int32_t DEFAULT_REFRESH_RATE = 1666666666;
constexpr int32_t DEFAULT_DPI = 320;
+constexpr int DEFAULT_CONFIG_ID = 0;
+
class DisplayTransactionTest : public testing::Test {
protected:
DisplayTransactionTest();
~DisplayTransactionTest() override;
- void setupComposer(int virtualDisplayCount);
- void setupPrimaryDisplay(int width, int height);
+ // --------------------------------------------------------------------
+ // Precondition helpers
- void expectFramebufferQueuePairCreation(int width, int height);
+ void setupComposer(int virtualDisplayCount);
+ void setupFakeHwcDisplay(hwc2_display_t displayId, DisplayDevice::DisplayType type, int width,
+ int height);
+
+ struct FakeDisplayDeviceFactory {
+ public:
+ FakeDisplayDeviceFactory(TestableSurfaceFlinger& flinger, sp<BBinder>& displayToken,
+ DisplayDevice::DisplayType type, int hwcId)
+ : mFlinger(flinger), mDisplayToken(displayToken), mType(type), mHwcId(hwcId) {}
+
+ sp<DisplayDevice> build() {
+ return new DisplayDevice(mFlinger.mFlinger.get(), mType, mHwcId, false, mDisplayToken,
+ mNativeWindow, mDisplaySurface, std::move(mRenderSurface), 0,
+ 0, false, false, HWC_POWER_MODE_NORMAL);
+ }
+
+ FakeDisplayDeviceFactory& setNativeWindow(const sp<ANativeWindow>& nativeWindow) {
+ mNativeWindow = nativeWindow;
+ return *this;
+ }
+
+ FakeDisplayDeviceFactory& setDisplaySurface(const sp<DisplaySurface>& displaySurface) {
+ mDisplaySurface = displaySurface;
+ return *this;
+ }
+
+ FakeDisplayDeviceFactory& setRenderSurface(std::unique_ptr<RE::Surface> renderSurface) {
+ mRenderSurface = std::move(renderSurface);
+ return *this;
+ }
+
+ TestableSurfaceFlinger& mFlinger;
+ sp<BBinder>& mDisplayToken;
+ DisplayDevice::DisplayType mType;
+ int mHwcId;
+ sp<ANativeWindow> mNativeWindow;
+ sp<DisplaySurface> mDisplaySurface;
+ std::unique_ptr<RE::Surface> mRenderSurface;
+ };
+
+ sp<BBinder> setupFakeExistingPhysicalDisplay(hwc2_display_t displayId,
+ DisplayDevice::DisplayType type);
+
+ void setupFakeBufferQueueFactory();
+ void setupFakeNativeWindowSurfaceFactory(int displayWidth, int displayHeight, bool critical,
+ bool async);
+ void expectFramebufferUsageSet(int width, int height, int grallocUsage);
+ void expectHwcHotplugCalls(hwc2_display_t displayId, int displayWidth, int displayHeight);
+
+ // --------------------------------------------------------------------
+ // Call expectation helpers
+
+ void expectRESurfaceCreationCalls();
+ void expectPhysicalDisplayDeviceCreationCalls(hwc2_display_t displayId, int displayWidth,
+ int displayHeight, bool critical, bool async);
+
+ // --------------------------------------------------------------------
+ // Postcondition helpers
+
+ bool hasTransactionFlagSet(int flag);
+ bool hasDisplayDevice(sp<IBinder> displayToken);
+ sp<DisplayDevice> getDisplayDevice(sp<IBinder> displayToken);
+ bool hasCurrentDisplayState(sp<IBinder> displayToken);
+ const DisplayDeviceState& getCurrentDisplayState(sp<IBinder> displayToken);
+ bool hasDrawingDisplayState(sp<IBinder> displayToken);
+ const DisplayDeviceState& getDrawingDisplayState(sp<IBinder> displayToken);
+
+ // --------------------------------------------------------------------
+ // Test instances
std::unordered_set<HWC2::Capability> mCapabilities;
TestableSurfaceFlinger mFlinger;
mock::EventThread* mEventThread = new mock::EventThread();
+ mock::EventControlThread* mEventControlThread = new mock::EventControlThread();
// These mocks are created by the test, but are destroyed by SurfaceFlinger
// by virtue of being stored into a std::unique_ptr. However we still need
// to keep a reference to them for use in setting up call expectations.
RE::mock::RenderEngine* mRenderEngine = new RE::mock::RenderEngine();
Hwc2::mock::Composer* mComposer = new Hwc2::mock::Composer();
+ mock::MessageQueue* mMessageQueue = new mock::MessageQueue();
+ mock::SurfaceInterceptor* mSurfaceInterceptor = new mock::SurfaceInterceptor();
// These mocks are created only when expected to be created via a factory.
sp<mock::GraphicBufferConsumer> mConsumer;
sp<mock::GraphicBufferProducer> mProducer;
- std::unique_ptr<HWC2Display> mDisplay;
+ mock::NativeWindowSurface* mNativeWindowSurface = nullptr;
+ sp<mock::NativeWindow> mNativeWindow;
+ RE::mock::Surface* mRenderSurface = nullptr;
+ std::vector<std::unique_ptr<HWC2Display>> mFakeHwcDisplays;
};
DisplayTransactionTest::DisplayTransactionTest() {
@@ -85,8 +170,16 @@
ADD_FAILURE() << "Unexpected request to create a buffer queue.";
});
+ mFlinger.setCreateNativeWindowSurface([](auto) {
+ ADD_FAILURE() << "Unexpected request to create a native window surface.";
+ return nullptr;
+ });
+
+ mFlinger.mutableEventControlThread().reset(mEventControlThread);
mFlinger.mutableEventThread().reset(mEventThread);
+ mFlinger.mutableEventQueue().reset(mMessageQueue);
mFlinger.setupRenderEngine(std::unique_ptr<RE::RenderEngine>(mRenderEngine));
+ mFlinger.mutableInterceptor().reset(mSurfaceInterceptor);
setupComposer(0);
}
@@ -106,26 +199,49 @@
Mock::VerifyAndClear(mComposer);
}
-void DisplayTransactionTest::setupPrimaryDisplay(int width, int height) {
- mDisplay = std::make_unique<HWC2Display>(*mComposer, mCapabilities, 0,
- HWC2::DisplayType::Physical);
+void DisplayTransactionTest::setupFakeHwcDisplay(hwc2_display_t displayId,
+ DisplayDevice::DisplayType type, int width,
+ int height) {
+ auto display = std::make_unique<HWC2Display>(*mComposer, mCapabilities, displayId,
+ HWC2::DisplayType::Physical);
+ display->mutableIsConnected() = true;
+ display->mutableConfigs().emplace(DEFAULT_CONFIG_ID,
+ HWC2::Display::Config::Builder(*display, DEFAULT_CONFIG_ID)
+ .setWidth(width)
+ .setHeight(height)
+ .setVsyncPeriod(DEFAULT_REFRESH_RATE)
+ .setDpiX(DEFAULT_DPI)
+ .setDpiY(DEFAULT_DPI)
+ .build());
- mDisplay->mutableIsConnected() = true;
- mDisplay->mutableConfigs().emplace(0,
- HWC2::Display::Config::Builder(*mDisplay, 0)
- .setWidth(width)
- .setHeight(height)
- .setVsyncPeriod(DEFAULT_REFRESH_RATE)
- .setDpiX(DEFAULT_DPI)
- .setDpiY(DEFAULT_DPI)
- .build());
+ mFlinger.mutableHwcDisplayData()[type].reset();
+ mFlinger.mutableHwcDisplayData()[type].hwcDisplay = display.get();
+ mFlinger.mutableHwcDisplaySlots().emplace(displayId, type);
- mFlinger.mutableHwcDisplayData()[DisplayDevice::DISPLAY_PRIMARY].reset();
- mFlinger.mutableHwcDisplayData()[DisplayDevice::DISPLAY_PRIMARY].hwcDisplay = mDisplay.get();
- mFlinger.mutableHwcDisplaySlots().emplace(0, DisplayDevice::DISPLAY_PRIMARY);
+ mFakeHwcDisplays.push_back(std::move(display));
}
-void DisplayTransactionTest::expectFramebufferQueuePairCreation(int width, int height) {
+sp<BBinder> DisplayTransactionTest::setupFakeExistingPhysicalDisplay(
+ hwc2_display_t displayId, DisplayDevice::DisplayType type) {
+ setupFakeHwcDisplay(displayId, type, 0, 0);
+
+ sp<BBinder> displayToken = new BBinder();
+ mFlinger.mutableBuiltinDisplays()[type] = displayToken;
+ mFlinger.mutableDisplays()
+ .add(displayToken,
+ FakeDisplayDeviceFactory(mFlinger, displayToken, type, type).build());
+
+ DisplayDeviceState state(type, true);
+ mFlinger.mutableCurrentState().displays.add(displayToken, state);
+ mFlinger.mutableDrawingState().displays.add(displayToken, state);
+
+ return displayToken;
+}
+
+void DisplayTransactionTest::setupFakeBufferQueueFactory() {
+ // This setup is only expected once per test.
+ ASSERT_TRUE(mConsumer == nullptr && mProducer == nullptr);
+
mConsumer = new mock::GraphicBufferConsumer();
mProducer = new mock::GraphicBufferProducer();
@@ -133,61 +249,187 @@
*outProducer = mProducer;
*outConsumer = mConsumer;
});
+}
+void DisplayTransactionTest::setupFakeNativeWindowSurfaceFactory(int displayWidth,
+ int displayHeight, bool critical,
+ bool async) {
+ // This setup is only expected once per test.
+ ASSERT_TRUE(mNativeWindowSurface == nullptr);
+
+ mNativeWindowSurface = new mock::NativeWindowSurface();
+ mNativeWindow = new mock::NativeWindow();
+
+ mFlinger.setCreateNativeWindowSurface(
+ [this](auto) { return std::unique_ptr<NativeWindowSurface>(mNativeWindowSurface); });
+
+ EXPECT_CALL(*mNativeWindowSurface, getNativeWindow()).WillOnce(Return(mNativeWindow));
+
+ EXPECT_CALL(*mNativeWindow, perform(19)).Times(1);
+
+ EXPECT_CALL(*mRenderSurface, setAsync(async)).Times(1);
+ EXPECT_CALL(*mRenderSurface, setCritical(critical)).Times(1);
+ EXPECT_CALL(*mRenderSurface, setNativeWindow(mNativeWindow.get())).Times(1);
+ EXPECT_CALL(*mRenderSurface, queryWidth()).WillOnce(Return(displayWidth));
+ EXPECT_CALL(*mRenderSurface, queryHeight()).WillOnce(Return(displayHeight));
+}
+
+void DisplayTransactionTest::expectFramebufferUsageSet(int width, int height, int grallocUsage) {
EXPECT_CALL(*mConsumer, consumerConnect(_, false)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(*mConsumer, setConsumerName(_)).WillRepeatedly(Return(NO_ERROR));
- EXPECT_CALL(*mConsumer,
- setConsumerUsageBits(GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER |
- GRALLOC_USAGE_HW_FB))
- .WillRepeatedly(Return(NO_ERROR));
+ EXPECT_CALL(*mConsumer, setConsumerUsageBits(grallocUsage)).WillRepeatedly(Return(NO_ERROR));
EXPECT_CALL(*mConsumer, setDefaultBufferSize(width, height)).WillRepeatedly(Return(NO_ERROR));
EXPECT_CALL(*mConsumer, setMaxAcquiredBufferCount(_)).WillRepeatedly(Return(NO_ERROR));
EXPECT_CALL(*mProducer, allocateBuffers(0, 0, 0, 0)).WillRepeatedly(Return());
}
-TEST_F(DisplayTransactionTest, processDisplayChangesLockedProcessesPrimaryDisplayConnected) {
- using android::hardware::graphics::common::V1_0::ColorMode;
+void DisplayTransactionTest::expectHwcHotplugCalls(hwc2_display_t displayId, int displayWidth,
+ int displayHeight) {
+ EXPECT_CALL(*mComposer, getDisplayType(displayId, _))
+ .WillOnce(DoAll(SetArgPointee<1>(IComposerClient::DisplayType::PHYSICAL),
+ Return(Error::NONE)));
+ EXPECT_CALL(*mComposer, setClientTargetSlotCount(_)).WillOnce(Return(Error::NONE));
+ EXPECT_CALL(*mComposer, getDisplayConfigs(_, _))
+ .WillOnce(DoAll(SetArgPointee<1>(std::vector<unsigned>{0}), Return(Error::NONE)));
+ EXPECT_CALL(*mComposer, getDisplayAttribute(displayId, 0, IComposerClient::Attribute::WIDTH, _))
+ .WillOnce(DoAll(SetArgPointee<3>(displayWidth), Return(Error::NONE)));
+ EXPECT_CALL(*mComposer,
+ getDisplayAttribute(displayId, 0, IComposerClient::Attribute::HEIGHT, _))
+ .WillOnce(DoAll(SetArgPointee<3>(displayHeight), Return(Error::NONE)));
+ EXPECT_CALL(*mComposer,
+ getDisplayAttribute(displayId, 0, IComposerClient::Attribute::VSYNC_PERIOD, _))
+ .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_REFRESH_RATE), Return(Error::NONE)));
+ EXPECT_CALL(*mComposer, getDisplayAttribute(displayId, 0, IComposerClient::Attribute::DPI_X, _))
+ .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
+ EXPECT_CALL(*mComposer, getDisplayAttribute(displayId, 0, IComposerClient::Attribute::DPI_Y, _))
+ .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
+}
- setupPrimaryDisplay(1920, 1080);
+void DisplayTransactionTest::expectRESurfaceCreationCalls() {
+ // This setup is only expected once per test.
+ ASSERT_TRUE(mRenderSurface == nullptr);
- sp<BBinder> token = new BBinder();
- mFlinger.mutableCurrentState().displays.add(token, {DisplayDevice::DISPLAY_PRIMARY, true});
+ mRenderSurface = new RE::mock::Surface();
+ EXPECT_CALL(*mRenderEngine, createSurface())
+ .WillOnce(Return(ByMove(std::unique_ptr<RE::Surface>(mRenderSurface))));
+}
- EXPECT_CALL(*mComposer, getActiveConfig(DisplayDevice::DISPLAY_PRIMARY, _))
- .WillOnce(DoAll(SetArgPointee<1>(0), Return(Error::NONE)));
- EXPECT_CALL(*mComposer, getColorModes(DisplayDevice::DISPLAY_PRIMARY, _)).Times(0);
- EXPECT_CALL(*mComposer, getHdrCapabilities(DisplayDevice::DISPLAY_PRIMARY, _, _, _, _))
+void DisplayTransactionTest::expectPhysicalDisplayDeviceCreationCalls(hwc2_display_t displayId,
+ int displayWidth,
+ int displayHeight,
+ bool critical, bool async) {
+ EXPECT_CALL(*mComposer, getActiveConfig(displayId, _))
+ .WillOnce(DoAll(SetArgPointee<1>(DEFAULT_CONFIG_ID), Return(Error::NONE)));
+ EXPECT_CALL(*mComposer, getColorModes(displayId, _)).Times(0);
+ EXPECT_CALL(*mComposer, getHdrCapabilities(displayId, _, _, _, _))
.WillOnce(DoAll(SetArgPointee<1>(std::vector<Hdr>()), Return(Error::NONE)));
- expectFramebufferQueuePairCreation(1920, 1080);
+ setupFakeBufferQueueFactory();
+ expectFramebufferUsageSet(displayWidth, displayHeight,
+ GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER |
+ GRALLOC_USAGE_HW_FB);
- auto reSurface = new RE::mock::Surface();
- EXPECT_CALL(*mRenderEngine, createSurface())
- .WillOnce(Return(ByMove(std::unique_ptr<RE::Surface>(reSurface))));
- EXPECT_CALL(*reSurface, setAsync(false)).Times(1);
- EXPECT_CALL(*reSurface, setCritical(true)).Times(1);
- EXPECT_CALL(*reSurface, setNativeWindow(_)).Times(1);
- EXPECT_CALL(*reSurface, queryWidth()).WillOnce(Return(1920));
- EXPECT_CALL(*reSurface, queryHeight()).WillOnce(Return(1080));
+ setupFakeNativeWindowSurfaceFactory(displayWidth, displayHeight, critical, async);
+}
+
+bool DisplayTransactionTest::hasTransactionFlagSet(int flag) {
+ return mFlinger.mutableTransactionFlags() & flag;
+}
+
+bool DisplayTransactionTest::hasDisplayDevice(sp<IBinder> displayToken) {
+ return mFlinger.mutableDisplays().indexOfKey(displayToken) >= 0;
+}
+
+sp<DisplayDevice> DisplayTransactionTest::getDisplayDevice(sp<IBinder> displayToken) {
+ return mFlinger.mutableDisplays().valueFor(displayToken);
+}
+
+bool DisplayTransactionTest::hasCurrentDisplayState(sp<IBinder> displayToken) {
+ return mFlinger.mutableCurrentState().displays.indexOfKey(displayToken) >= 0;
+}
+
+const DisplayDeviceState& DisplayTransactionTest::getCurrentDisplayState(sp<IBinder> displayToken) {
+ return mFlinger.mutableCurrentState().displays.valueFor(displayToken);
+}
+
+bool DisplayTransactionTest::hasDrawingDisplayState(sp<IBinder> displayToken) {
+ return mFlinger.mutableDrawingState().displays.indexOfKey(displayToken) >= 0;
+}
+
+const DisplayDeviceState& DisplayTransactionTest::getDrawingDisplayState(sp<IBinder> displayToken) {
+ return mFlinger.mutableDrawingState().displays.valueFor(displayToken);
+}
+
+/* ------------------------------------------------------------------------
+ * SurfaceFlinger::handleTransactionLocked(eDisplayTransactionNeeded)
+ */
+
+TEST_F(DisplayTransactionTest, handleTransactionLockedProcessesHotplugConnectPrimary) {
+ constexpr hwc2_display_t externalDisplayId = 102;
+ constexpr hwc2_display_t displayId = 123;
+ constexpr int displayWidth = 1920;
+ constexpr int displayHeight = 1080;
+
+ // --------------------------------------------------------------------
+ // Preconditions
+
+ // An external display may already be set up
+ setupFakeHwcDisplay(externalDisplayId, DisplayDevice::DISPLAY_EXTERNAL, 3840, 2160);
+
+ // A hotplug connect comes in for a new display
+ mFlinger.mutablePendingHotplugEvents().emplace_back(
+ HotplugEvent{displayId, HWC2::Connection::Connected});
+
+ // --------------------------------------------------------------------
+ // Call Expectations
+
+ EXPECT_CALL(*mComposer, isUsingVrComposer()).WillOnce(Return(false));
+ expectHwcHotplugCalls(displayId, displayWidth, displayHeight);
+ expectRESurfaceCreationCalls();
+ expectPhysicalDisplayDeviceCreationCalls(displayId, displayWidth, displayHeight, true, false);
+
+ EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1);
EXPECT_CALL(*mEventThread, onHotplugReceived(DisplayDevice::DISPLAY_PRIMARY, true)).Times(1);
- mFlinger.processDisplayChangesLocked();
+ // --------------------------------------------------------------------
+ // Invocation
- ASSERT_TRUE(mFlinger.mutableDisplays().indexOfKey(token) >= 0);
+ mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
- const auto& device = mFlinger.mutableDisplays().valueFor(token);
- ASSERT_TRUE(device.get());
+ // --------------------------------------------------------------------
+ // Postconditions
+
+ // HWComposer should have an entry for the display
+ EXPECT_TRUE(mFlinger.mutableHwcDisplaySlots().count(displayId) == 1);
+
+ // The display should have set up as a primary built-in display.
+ auto displayToken = mFlinger.mutableBuiltinDisplays()[DisplayDevice::DISPLAY_PRIMARY];
+ ASSERT_TRUE(displayToken != nullptr);
+
+ // The display device should have been set up in the list of displays.
+ ASSERT_TRUE(hasDisplayDevice(displayToken));
+ const auto& device = getDisplayDevice(displayToken);
EXPECT_TRUE(device->isSecure());
EXPECT_TRUE(device->isPrimary());
- ssize_t i = mFlinger.mutableDrawingState().displays.indexOfKey(token);
- ASSERT_GE(0, i);
- const auto& draw = mFlinger.mutableDrawingState().displays[i];
+ // The display should have been set up in the current display state
+ ASSERT_TRUE(hasCurrentDisplayState(displayToken));
+ const auto& current = getCurrentDisplayState(displayToken);
+ EXPECT_EQ(DisplayDevice::DISPLAY_PRIMARY, current.type);
+
+ // The display should have been set up in the drawing display state
+ ASSERT_TRUE(hasDrawingDisplayState(displayToken));
+ const auto& draw = getDrawingDisplayState(displayToken);
EXPECT_EQ(DisplayDevice::DISPLAY_PRIMARY, draw.type);
- EXPECT_CALL(*mConsumer, consumerDisconnect()).Times(1);
+ // --------------------------------------------------------------------
+ // Cleanup conditions
+
+ EXPECT_CALL(*mComposer, setVsyncEnabled(displayId, IComposerClient::Vsync::DISABLE))
+ .WillOnce(Return(Error::NONE));
+ EXPECT_CALL(*mConsumer, consumerDisconnect()).WillOnce(Return(NO_ERROR));
}
} // namespace
diff --git a/services/surfaceflinger/tests/unittests/MockNativeWindowSurface.cpp b/services/surfaceflinger/tests/unittests/MockNativeWindowSurface.cpp
new file mode 100644
index 0000000..0314568
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/MockNativeWindowSurface.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MockNativeWindowSurface.h"
+
+namespace android {
+namespace mock {
+
+// Explicit default instantiation is recommended.
+NativeWindowSurface::NativeWindowSurface() = default;
+NativeWindowSurface::~NativeWindowSurface() = default;
+
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/MockNativeWindowSurface.h b/services/surfaceflinger/tests/unittests/MockNativeWindowSurface.h
new file mode 100644
index 0000000..88d1a9f
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/MockNativeWindowSurface.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include <system/window.h> // for ANativeWindow
+
+#include "SurfaceFlinger.h" // for base NativeWindowSurface
+
+namespace android {
+namespace mock {
+
+class NativeWindowSurface : public android::NativeWindowSurface {
+public:
+ NativeWindowSurface();
+ ~NativeWindowSurface();
+
+ MOCK_CONST_METHOD0(getNativeWindow, sp<ANativeWindow>());
+ MOCK_METHOD0(preallocateBuffers, void());
+};
+
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 3e58eb8..2dd8e5f 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -45,26 +45,40 @@
}
using CreateBufferQueueFunction = SurfaceFlinger::CreateBufferQueueFunction;
-
void setCreateBufferQueueFunction(CreateBufferQueueFunction f) {
mFlinger->mCreateBufferQueue = f;
}
+ using CreateNativeWindowSurfaceFunction = SurfaceFlinger::CreateNativeWindowSurfaceFunction;
+ void setCreateNativeWindowSurface(CreateNativeWindowSurfaceFunction f) {
+ mFlinger->mCreateNativeWindowSurface = f;
+ }
+
+ using HotplugEvent = SurfaceFlinger::HotplugEvent;
+
/* ------------------------------------------------------------------------
* Forwarding for functions being tested
*/
- auto processDisplayChangesLocked() { return mFlinger->processDisplayChangesLocked(); }
+
+ auto handleTransactionLocked(uint32_t transactionFlags) {
+ return mFlinger->handleTransactionLocked(transactionFlags);
+ }
/* ------------------------------------------------------------------------
* Read-write access to private data to set up preconditions and assert
* post-conditions.
*/
+
auto& mutableBuiltinDisplays() { return mFlinger->mBuiltinDisplays; }
- auto& mutableDisplays() { return mFlinger->mDisplays; }
auto& mutableCurrentState() { return mFlinger->mCurrentState; }
+ auto& mutableDisplays() { return mFlinger->mDisplays; }
auto& mutableDrawingState() { return mFlinger->mDrawingState; }
- auto& mutableEventThread() { return mFlinger->mEventThread; }
+ auto& mutableEventControlThread() { return mFlinger->mEventControlThread; }
auto& mutableEventQueue() { return mFlinger->mEventQueue; }
+ auto& mutableEventThread() { return mFlinger->mEventThread; }
+ auto& mutableInterceptor() { return mFlinger->mInterceptor; }
+ auto& mutablePendingHotplugEvents() { return mFlinger->mPendingHotplugEvents; }
+ auto& mutableTransactionFlags() { return mFlinger->mTransactionFlags; }
auto& mutableHwcDisplayData() { return mFlinger->getBE().mHwc->mDisplayData; }
auto& mutableHwcDisplaySlots() { return mFlinger->getBE().mHwc->mHwcDisplaySlots; }
@@ -75,7 +89,10 @@
// still be referenced by something despite our best efforts to destroy
// it after each test is done.
mutableDisplays().clear();
+ mutableEventControlThread().reset();
+ mutableEventQueue().reset();
mutableEventThread().reset();
+ mutableInterceptor().reset();
mFlinger->getBE().mHwc.reset();
mFlinger->getBE().mRenderEngine.reset();
}