Merge "surfaceflinger: simplify HWC buffer cache clean up"
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 89779af..73184db 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -25,6 +25,7 @@
DisplayHardware/ComposerHal.cpp \
DisplayHardware/FramebufferSurface.cpp \
DisplayHardware/HWC2.cpp \
+ DisplayHardware/HWComposerBufferCache.cpp \
DisplayHardware/PowerHAL.cpp \
DisplayHardware/VirtualDisplaySurface.cpp \
Effects/Daltonizer.cpp \
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index d384bb1..92a7794 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -137,7 +137,7 @@
status_t err = acquireBufferLocked(&item, 0);
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
#ifdef USE_HWC2
- mHwcBufferCache->getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
+ mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
&outSlot, &outBuffer);
#else
outBuffer = mCurrentBuffer;
@@ -178,7 +178,7 @@
outFence = item.mFence;
#ifdef USE_HWC2
- mHwcBufferCache->getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
+ mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
&outSlot, &outBuffer);
outDataspace = item.mDataSpace;
#else
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 5eea6b6..69a72d7 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -18,14 +18,13 @@
#define ANDROID_SF_FRAMEBUFFER_SURFACE_H
#include "DisplaySurface.h"
+#include "HWComposerBufferCache.h"
#include <stdint.h>
#include <sys/types.h>
#include <gui/ConsumerBase.h>
-#include <memory>
-
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
@@ -33,7 +32,6 @@
class Rect;
class String8;
class HWComposer;
-class HWComposerBufferCache;
// ---------------------------------------------------------------------------
@@ -96,8 +94,7 @@
HWComposer& mHwc;
#ifdef USE_HWC2
- std::unique_ptr<HWComposerBufferCache> mHwcBufferCache =
- std::make_unique<HWComposerBufferCache>();
+ HWComposerBufferCache mHwcBufferCache;
// Previous buffer to release after getting an updated retire fence
bool mHasPendingRelease;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index e1138af..6644bd9 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -925,41 +925,5 @@
*this = DisplayData();
}
-void HWComposerBufferCache::clear()
-{
- mBuffers.clear();
-}
-
-void HWComposerBufferCache::getHwcBuffer(int slot,
- const sp<GraphicBuffer>& buffer,
- uint32_t* outSlot, sp<GraphicBuffer>* outBuffer)
-{
-#ifdef BYPASS_IHWC
- *outSlot = slot;
- *outBuffer = buffer;
-#else
- if (slot == BufferQueue::INVALID_BUFFER_SLOT || slot < 0) {
- // default to slot 0
- slot = 0;
- }
-
- if (static_cast<size_t>(slot) >= mBuffers.size()) {
- mBuffers.resize(slot + 1);
- }
-
- *outSlot = slot;
-
- if (mBuffers[slot] == buffer) {
- // already cached in HWC, skip sending the buffer
- *outBuffer = nullptr;
- } else {
- *outBuffer = buffer;
-
- // update cache
- mBuffers[slot] = buffer;
- }
-#endif
-}
-
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 20cca39..117db4a 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -26,8 +26,6 @@
#include <stdint.h>
#include <sys/types.h>
-#include <gui/BufferQueue.h>
-
#include <ui/Fence.h>
#include <utils/BitSet.h>
@@ -236,19 +234,6 @@
mutable std::atomic<bool> mDumpMayLockUp;
};
-class HWComposerBufferCache {
-public:
- void clear();
-
- void getHwcBuffer(int slot, const sp<GraphicBuffer>& buffer,
- uint32_t* outSlot, sp<GraphicBuffer>* outBuffer);
-
-private:
- // a vector as we expect "slot" to be in the range of [0, 63] (that is,
- // less than BufferQueue::NUM_BUFFER_SLOTS).
- std::vector<sp<GraphicBuffer>> mBuffers;
-};
-
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp b/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp
new file mode 100644
index 0000000..6b91224
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 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 "HWComposerBufferCache.h"
+
+#include <gui/BufferQueue.h>
+
+namespace android {
+
+HWComposerBufferCache::HWComposerBufferCache()
+{
+ mBuffers.reserve(BufferQueue::NUM_BUFFER_SLOTS);
+}
+
+void HWComposerBufferCache::getHwcBuffer(int slot,
+ const sp<GraphicBuffer>& buffer,
+ uint32_t* outSlot, sp<GraphicBuffer>* outBuffer)
+{
+#ifdef BYPASS_IHWC
+ *outSlot = slot;
+ *outBuffer = buffer;
+#else
+ if (slot == BufferQueue::INVALID_BUFFER_SLOT || slot < 0) {
+ // default to slot 0
+ slot = 0;
+ }
+
+ if (static_cast<size_t>(slot) >= mBuffers.size()) {
+ mBuffers.resize(slot + 1);
+ }
+
+ *outSlot = slot;
+
+ if (mBuffers[slot] == buffer) {
+ // already cached in HWC, skip sending the buffer
+ *outBuffer = nullptr;
+ } else {
+ *outBuffer = buffer;
+
+ // update cache
+ mBuffers[slot] = buffer;
+ }
+#endif
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.h b/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.h
new file mode 100644
index 0000000..a008ca9
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ANDROID_SF_HWCOMPOSERBUFFERCACHE_H
+#define ANDROID_SF_HWCOMPOSERBUFFERCACHE_H
+
+#include <stdint.h>
+
+#include <utils/StrongPointer.h>
+
+#include <vector>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+class GraphicBuffer;
+
+// With HIDLized hwcomposer HAL, the HAL can maintain a buffer cache for each
+// HWC display and layer. When updating a display target or a layer buffer,
+// we have the option to send the buffer handle over or to request the HAL to
+// retrieve it from its cache. The latter is cheaper since it eliminates the
+// overhead to transfer the handle over the trasport layer, and the overhead
+// for the HAL to clone and retain the handle.
+//
+// To be able to find out whether a buffer is already in the HAL's cache, we
+// use HWComposerBufferCache to mirror the cache in SF.
+class HWComposerBufferCache {
+public:
+ HWComposerBufferCache();
+
+ // Given a buffer queue slot and buffer, return the HWC cache slot and
+ // buffer to be sent to HWC.
+ //
+ // outBuffer is set to buffer when buffer is not in the HWC cache;
+ // otherwise, outBuffer is set to nullptr.
+ void getHwcBuffer(int slot, const sp<GraphicBuffer>& buffer,
+ uint32_t* outSlot, sp<GraphicBuffer>* outBuffer);
+
+private:
+ // a vector as we expect "slot" to be in the range of [0, 63] (that is,
+ // less than BufferQueue::NUM_BUFFER_SLOTS).
+ std::vector<sp<GraphicBuffer>> mBuffers;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_SF_HWCOMPOSERBUFFERCACHE_H
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index c5a4f99..6f253ab 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -224,7 +224,7 @@
#ifdef USE_HWC2
uint32_t hwcSlot = 0;
sp<GraphicBuffer> hwcBuffer;
- mHwcBufferCache->getHwcBuffer(mFbProducerSlot, fbBuffer,
+ mHwcBufferCache.getHwcBuffer(mFbProducerSlot, fbBuffer,
&hwcSlot, &hwcBuffer);
// TODO: Correctly propagate the dataspace from GL composition
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index fb5fcc8..ee2772a 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -18,18 +18,16 @@
#define ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
#include "DisplaySurface.h"
+#include "HWComposerBufferCache.h"
#include <gui/ConsumerBase.h>
#include <gui/IGraphicBufferProducer.h>
-#include <memory>
-
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
class HWComposer;
-class HWComposerBufferCache;
class IProducerListener;
/* This DisplaySurface implementation supports virtual displays, where GLES
@@ -255,8 +253,7 @@
bool mMustRecompose;
#ifdef USE_HWC2
- std::unique_ptr<HWComposerBufferCache> mHwcBufferCache =
- std::make_unique<HWComposerBufferCache>();
+ HWComposerBufferCache mHwcBufferCache;
#endif
};
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 7a4ace9..51984b7 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -276,16 +276,6 @@
}
}
-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
@@ -780,7 +770,8 @@
const auto& viewport = displayDevice->getViewport();
Region visible = tr.transform(visibleRegion.intersect(viewport));
auto hwcId = displayDevice->getHwcDisplayId();
- auto& hwcLayer = mHwcLayers[hwcId].layer;
+ auto& hwcInfo = mHwcLayers[hwcId];
+ auto& hwcLayer = hwcInfo.layer;
auto error = hwcLayer->setVisibleRegion(visible);
if (error != HWC2::Error::None) {
ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(),
@@ -809,7 +800,7 @@
}
// Client layers
- if (mHwcLayers[hwcId].forceClientComposition ||
+ if (hwcInfo.forceClientComposition ||
(mActiveBuffer != nullptr && mActiveBuffer->handle == nullptr)) {
ALOGV("[%s] Requesting Client composition", mName.string());
setCompositionType(hwcId, HWC2::Composition::Client);
@@ -858,11 +849,8 @@
uint32_t hwcSlot = 0;
buffer_handle_t hwcHandle = nullptr;
{
- Mutex::Autolock lock(mHwcBufferCacheMutex);
-
- auto& hwcBufferCache = mHwcBufferCaches[hwcId];
sp<GraphicBuffer> hwcBuffer;
- hwcBufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
+ hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
&hwcSlot, &hwcBuffer);
if (hwcBuffer != nullptr) {
hwcHandle = hwcBuffer->handle;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 0efdf54..6b228b0 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -47,6 +47,7 @@
#include "Transform.h"
#include "DisplayHardware/HWComposer.h"
+#include "DisplayHardware/HWComposerBufferCache.h"
#include "RenderEngine/Mesh.h"
#include "RenderEngine/Texture.h"
@@ -383,20 +384,13 @@
#ifdef USE_HWC2
// -----------------------------------------------------------------------
- void eraseHwcLayer(int32_t hwcId) {
- mHwcLayers.erase(hwcId);
-
- Mutex::Autolock lock(mHwcBufferCacheMutex);
- mHwcBufferCaches.erase(hwcId);
- }
-
bool hasHwcLayer(int32_t hwcId) {
if (mHwcLayers.count(hwcId) == 0) {
return false;
}
if (mHwcLayers[hwcId].layer->isAbandoned()) {
ALOGI("Erasing abandoned layer %s on %d", mName.string(), hwcId);
- eraseHwcLayer(hwcId);
+ mHwcLayers.erase(hwcId);
return false;
}
return true;
@@ -412,11 +406,8 @@
void setHwcLayer(int32_t hwcId, std::shared_ptr<HWC2::Layer>&& layer) {
if (layer) {
mHwcLayers[hwcId].layer = layer;
-
- Mutex::Autolock lock(mHwcBufferCacheMutex);
- mHwcBufferCaches[hwcId] = HWComposerBufferCache();
} else {
- eraseHwcLayer(hwcId);
+ mHwcLayers.erase(hwcId);
}
}
@@ -511,7 +502,6 @@
// Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener
virtual void onFrameAvailable(const BufferItem& item) override;
virtual void onFrameReplaced(const BufferItem& item) override;
- virtual void onBuffersReleased() override;
virtual void onSidebandStreamChanged() override;
void commitTransaction(const State& stateToCommit);
@@ -703,6 +693,7 @@
bool clearClientTarget;
Rect displayFrame;
FloatRect sourceCrop;
+ HWComposerBufferCache bufferCache;
};
// A layer can be attached to multiple displays when operating in mirror mode
@@ -710,12 +701,6 @@
// case we need to keep track. In non-mirror mode, a layer will have only one
// HWCInfo. This map key is a display layerStack.
std::unordered_map<int32_t, HWCInfo> mHwcLayers;
-
- // We need one HWComposerBufferCache for each HWC display. We cannot have
- // HWComposerBufferCache in HWCInfo because HWCInfo can only be accessed
- // from the main thread.
- Mutex mHwcBufferCacheMutex;
- std::unordered_map<int32_t, HWComposerBufferCache> mHwcBufferCaches;
#else
bool mIsGlesComposition;
#endif
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index b00792b..01226e0 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -237,19 +237,6 @@
mContentsChangedListener = listener;
}
-void SurfaceFlingerConsumer::onBuffersReleased() {
- sp<ContentsChangedListener> listener;
- { // scope for the lock
- Mutex::Autolock lock(mMutex);
- ALOG_ASSERT(mFrameAvailableListener.unsafe_get() == mContentsChangedListener.unsafe_get());
- listener = mContentsChangedListener.promote();
- }
-
- if (listener != NULL) {
- listener->onBuffersReleased();
- }
-}
-
void SurfaceFlingerConsumer::onSidebandStreamChanged() {
sp<ContentsChangedListener> listener;
{ // scope for the lock
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h
index cfa70ed..1126233 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.h
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -35,7 +35,6 @@
static const status_t BUFFER_REJECTED = UNKNOWN_ERROR + 8;
struct ContentsChangedListener: public FrameAvailableListener {
- virtual void onBuffersReleased() = 0;
virtual void onSidebandStreamChanged() = 0;
};
@@ -93,7 +92,6 @@
FrameEventHistoryDelta* outDelta) override;
private:
- virtual void onBuffersReleased();
virtual void onSidebandStreamChanged();
wp<ContentsChangedListener> mContentsChangedListener;