DisplayHardware/ComposerHal.cpp \
DisplayHardware/FramebufferSurface.cpp \
DisplayHardware/HWC2.cpp \
+ DisplayHardware/HWComposerBufferCache.cpp \
DisplayHardware/PowerHAL.cpp \
DisplayHardware/VirtualDisplaySurface.cpp \
Effects/Daltonizer.cpp \
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;
outFence = item.mFence;
#ifdef USE_HWC2
- mHwcBufferCache->getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
+ mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
&outSlot, &outBuffer);
outDataspace = item.mDataSpace;
#else
#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 {
// ---------------------------------------------------------------------------
class Rect;
class String8;
class HWComposer;
-class HWComposerBufferCache;
// ---------------------------------------------------------------------------
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;
*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
#include <stdint.h>
#include <sys/types.h>
-#include <gui/BufferQueue.h>
-
#include <ui/Fence.h>
#include <utils/BitSet.h>
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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
#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
#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
bool mMustRecompose;
#ifdef USE_HWC2
- std::unique_ptr<HWComposerBufferCache> mHwcBufferCache =
- std::make_unique<HWComposerBufferCache>();
+ HWComposerBufferCache mHwcBufferCache;
#endif
};
}
}
-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
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(),
}
// 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);
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;
#include "Transform.h"
#include "DisplayHardware/HWComposer.h"
+#include "DisplayHardware/HWComposerBufferCache.h"
#include "RenderEngine/Mesh.h"
#include "RenderEngine/Texture.h"
#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;
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);
}
}
// 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);
bool clearClientTarget;
Rect displayFrame;
FloatRect sourceCrop;
+ HWComposerBufferCache bufferCache;
};
// A layer can be attached to multiple displays when operating in mirror mode
// 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
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
static const status_t BUFFER_REJECTED = UNKNOWN_ERROR + 8;
struct ContentsChangedListener: public FrameAvailableListener {
- virtual void onBuffersReleased() = 0;
virtual void onSidebandStreamChanged() = 0;
};
FrameEventHistoryDelta* outDelta) override;
private:
- virtual void onBuffersReleased();
virtual void onSidebandStreamChanged();
wp<ContentsChangedListener> mContentsChangedListener;