Push HWC cache slot generation down into CompositionEngine
Stop caching buffers inside SurfaceFlinger and remove the tight coupling
between SurfaceFlinger's ClientCache and the Hardware Composer cache.
This allows a better seperation of responsibility, where buffer cache
management is not split between HwcSlotGenerator and HwcBufferCache, but
is instead solely handled by HwcBufferCache.
Note that FramebufferSurface and VirtualDisplaySurface no longer use
HwcBufferCache, but instead use their own cache slot management that
is solely based on BufferQueue slot numbers.
Also do minor refactoring in FramebufferSurface to simplify code.
Bug: 258196272
Test: started and stopped multiple YouTube videos on adt4 and verified
no change in graphic buffer usage
Test: atest HwcBufferCacheTest
Test: atest OutputPrepareTest
Change-Id: Ica7955ab4bc70e3c70207390e36dff73a2fc4949
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index eb14933..ce602a8 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -72,6 +72,10 @@
mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height);
mConsumer->setMaxAcquiredBufferCount(
SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1);
+
+ for (size_t i = 0; i < sizeof(mHwcBufferIds) / sizeof(mHwcBufferIds[0]); ++i) {
+ mHwcBufferIds[i] = UINT64_MAX;
+ }
}
void FramebufferSurface::resizeBuffers(const ui::Size& newSize) {
@@ -88,31 +92,16 @@
}
status_t FramebufferSurface::advanceFrame() {
- uint32_t slot = 0;
- sp<GraphicBuffer> buf;
- sp<Fence> acquireFence(Fence::NO_FENCE);
- Dataspace dataspace = Dataspace::UNKNOWN;
- status_t result = nextBuffer(slot, buf, acquireFence, dataspace);
- mDataSpace = dataspace;
- if (result != NO_ERROR) {
- ALOGE("error latching next FramebufferSurface buffer: %s (%d)",
- strerror(-result), result);
- }
- return result;
-}
-
-status_t FramebufferSurface::nextBuffer(uint32_t& outSlot,
- sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence,
- Dataspace& outDataspace) {
Mutex::Autolock lock(mMutex);
BufferItem item;
status_t err = acquireBufferLocked(&item, 0);
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
- mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer, &outSlot, &outBuffer);
+ mDataspace = Dataspace::UNKNOWN;
return NO_ERROR;
} else if (err != NO_ERROR) {
ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err);
+ mDataspace = Dataspace::UNKNOWN;
return err;
}
@@ -133,13 +122,18 @@
mCurrentBufferSlot = item.mSlot;
mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
mCurrentFence = item.mFence;
+ mDataspace = static_cast<Dataspace>(item.mDataSpace);
- outFence = item.mFence;
- mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer, &outSlot, &outBuffer);
- outDataspace = static_cast<Dataspace>(item.mDataSpace);
- status_t result = mHwc.setClientTarget(mDisplayId, outSlot, outFence, outBuffer, outDataspace);
+ // assume HWC has previously seen the buffer in this slot
+ sp<GraphicBuffer> hwcBuffer = sp<GraphicBuffer>(nullptr);
+ if (mCurrentBuffer->getId() != mHwcBufferIds[mCurrentBufferSlot]) {
+ mHwcBufferIds[mCurrentBufferSlot] = mCurrentBuffer->getId();
+ hwcBuffer = mCurrentBuffer; // HWC hasn't previously seen this buffer in this slot
+ }
+ status_t result = mHwc.setClientTarget(mDisplayId, mCurrentBufferSlot, mCurrentFence, hwcBuffer,
+ mDataspace);
if (result != NO_ERROR) {
- ALOGE("error posting framebuffer: %d", result);
+ ALOGE("error posting framebuffer: %s (%d)", strerror(-result), result);
return result;
}
@@ -190,7 +184,7 @@
limitedSize.width = maxSize.height * aspectRatio;
wasLimited = true;
}
- ALOGI_IF(wasLimited, "framebuffer size has been limited to [%dx%d] from [%dx%d]",
+ ALOGI_IF(wasLimited, "Framebuffer size has been limited to [%dx%d] from [%dx%d]",
limitedSize.width, limitedSize.height, size.width, size.height);
return limitedSize;
}
@@ -198,9 +192,9 @@
void FramebufferSurface::dumpAsString(String8& result) const {
Mutex::Autolock lock(mMutex);
result.append(" FramebufferSurface\n");
- result.appendFormat(" mDataSpace=%s (%d)\n",
- dataspaceDetails(static_cast<android_dataspace>(mDataSpace)).c_str(),
- mDataSpace);
+ result.appendFormat(" mDataspace=%s (%d)\n",
+ dataspaceDetails(static_cast<android_dataspace>(mDataspace)).c_str(),
+ mDataspace);
ConsumerBase::dumpLocked(result, " ");
}
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index d41a856..0b863da 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -21,7 +21,7 @@
#include <sys/types.h>
#include <compositionengine/DisplaySurface.h>
-#include <compositionengine/impl/HwcBufferCache.h>
+#include <gui/BufferQueue.h>
#include <gui/ConsumerBase.h>
#include <ui/DisplayId.h>
#include <ui/Size.h>
@@ -69,12 +69,6 @@
virtual void dumpLocked(String8& result, const char* prefix) const;
- // nextBuffer waits for and then latches the next buffer from the
- // BufferQueue and releases the previously latched buffer to the
- // BufferQueue. The new buffer is returned in the 'buffer' argument.
- status_t nextBuffer(uint32_t& outSlot, sp<GraphicBuffer>& outBuffer,
- sp<Fence>& outFence, ui::Dataspace& outDataspace);
-
const PhysicalDisplayId mDisplayId;
// Framebuffer size has a dimension limitation in pixels based on the graphics capabilities of
@@ -91,7 +85,7 @@
// compositing. Otherwise it will display the dataspace of the buffer
// use for compositing which can change as wide-color content is
// on/off.
- ui::Dataspace mDataSpace;
+ ui::Dataspace mDataspace;
// mCurrentBuffer is the current buffer or nullptr to indicate that there is
// no current buffer.
@@ -103,7 +97,9 @@
// Hardware composer, owned by SurfaceFlinger.
HWComposer& mHwc;
- compositionengine::impl::HwcBufferCache mHwcBufferCache;
+ // Buffers that HWC has seen before, indexed by slot number.
+ // NOTE: The BufferQueue slot number is the same as the HWC slot number.
+ uint64_t mHwcBufferIds[BufferQueue::NUM_BUFFER_SLOTS];
// Previous buffer to release after getting an updated retire fence
bool mHasPendingRelease;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 3803a78..d62075e 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -103,6 +103,10 @@
sink->setAsyncMode(true);
IGraphicBufferProducer::QueueBufferOutput output;
mSource[SOURCE_SCRATCH]->connect(nullptr, NATIVE_WINDOW_API_EGL, false, &output);
+
+ for (size_t i = 0; i < sizeof(mHwcBufferIds) / sizeof(mHwcBufferIds[0]); ++i) {
+ mHwcBufferIds[i] = UINT64_MAX;
+ }
}
VirtualDisplaySurface::~VirtualDisplaySurface() {
@@ -197,9 +201,9 @@
return NO_MEMORY;
}
- sp<GraphicBuffer> fbBuffer = mFbProducerSlot >= 0 ?
- mProducerBuffers[mFbProducerSlot] : sp<GraphicBuffer>(nullptr);
- sp<GraphicBuffer> outBuffer = mProducerBuffers[mOutputProducerSlot];
+ sp<GraphicBuffer> const& fbBuffer =
+ mFbProducerSlot >= 0 ? mProducerBuffers[mFbProducerSlot] : sp<GraphicBuffer>(nullptr);
+ sp<GraphicBuffer> const& outBuffer = mProducerBuffers[mOutputProducerSlot];
VDS_LOGV("%s: fb=%d(%p) out=%d(%p)", __func__, mFbProducerSlot, fbBuffer.get(),
mOutputProducerSlot, outBuffer.get());
@@ -211,12 +215,14 @@
status_t result = NO_ERROR;
if (fbBuffer != nullptr) {
- uint32_t hwcSlot = 0;
- sp<GraphicBuffer> hwcBuffer;
- mHwcBufferCache.getHwcBuffer(mFbProducerSlot, fbBuffer, &hwcSlot, &hwcBuffer);
-
+ // assume that HWC has previously seen the buffer in this slot
+ sp<GraphicBuffer> hwcBuffer = sp<GraphicBuffer>(nullptr);
+ if (fbBuffer->getId() != mHwcBufferIds[mFbProducerSlot]) {
+ mHwcBufferIds[mFbProducerSlot] = fbBuffer->getId();
+ hwcBuffer = fbBuffer; // HWC hasn't previously seen this buffer in this slot
+ }
// TODO: Correctly propagate the dataspace from GL composition
- result = mHwc.setClientTarget(*halDisplayId, hwcSlot, mFbFence, hwcBuffer,
+ result = mHwc.setClientTarget(*halDisplayId, mFbProducerSlot, mFbFence, hwcBuffer,
ui::Dataspace::UNKNOWN);
}
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index e21095a..be06e2b 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -20,7 +20,7 @@
#include <string>
#include <compositionengine/DisplaySurface.h>
-#include <compositionengine/impl/HwcBufferCache.h>
+#include <gui/BufferQueue.h>
#include <gui/ConsumerBase.h>
#include <gui/IGraphicBufferProducer.h>
#include <ui/DisplayId.h>
@@ -164,6 +164,10 @@
sp<IGraphicBufferProducer> mSource[2]; // indexed by SOURCE_*
uint32_t mDefaultOutputFormat;
+ // Buffers that HWC has seen before, indexed by HWC slot number.
+ // NOTE: The BufferQueue slot number is the same as the HWC slot number.
+ uint64_t mHwcBufferIds[BufferQueue::NUM_BUFFER_SLOTS];
+
//
// Inter-frame state
//
@@ -260,8 +264,6 @@
bool mMustRecompose = false;
- compositionengine::impl::HwcBufferCache mHwcBufferCache;
-
bool mForceHwcCopy;
};