surfaceflinger: cache HWC client targets and buffers
Remember HWC client targets and buffers, and make sure we send each
unique slot/handle pair only once. This allows the composer to
clone/register/retain each buffer only once.
Test: builds and boots
Change-Id: Ib485189043a9c132031e82d4d7380ace3bf9453d
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index e57c19a..3a9bca6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -270,6 +270,16 @@
}
}
+void Layer::onBuffersReleased() {
+#ifdef USE_HWC2
+ Mutex::Autolock lock(mHwcBufferCacheMutex);
+
+ for (auto info : mHwcBufferCaches) {
+ info.second.clear();
+ }
+#endif
+}
+
void Layer::onSidebandStreamChanged() {
if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) {
// mSidebandStreamChanged was false
@@ -836,8 +846,22 @@
static_cast<int32_t>(error));
}
+ uint32_t hwcSlot = 0;
+ buffer_handle_t hwcHandle = nullptr;
+ {
+ Mutex::Autolock lock(mHwcBufferCacheMutex);
+
+ auto& hwcBufferCache = mHwcBufferCaches[hwcId];
+ sp<GraphicBuffer> hwcBuffer;
+ hwcBufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
+ &hwcSlot, &hwcBuffer);
+ if (hwcBuffer != nullptr) {
+ hwcHandle = hwcBuffer->handle;
+ }
+ }
+
auto acquireFence = mSurfaceFlingerConsumer->getCurrentFence();
- error = hwcLayer->setBuffer(mActiveBuffer->handle, acquireFence);
+ error = hwcLayer->setBuffer(hwcSlot, hwcHandle, acquireFence);
if (error != HWC2::Error::None) {
ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(),
mActiveBuffer->handle, to_string(error).c_str(),
@@ -2087,7 +2111,8 @@
}
// update the active buffer
- mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer();
+ mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer(
+ &mActiveBufferSlot);
if (mActiveBuffer == NULL) {
// this can only happen if the very first buffer was rejected.
return outDirtyRegion;