composer: refactor ComposerResources into shared library
composer@2.x-hal is a header library. Any of the shared
libraries it depends on must also be included by anyone
who includes composer@2.x-hal. This means when we add a new
version of mapper, anyone who uses composer@2.x-hal must
also include the new version of the mapper. Vendors
that depend on composer@2.x-hal are broken every time we
add a new mapper.
This patch refactors ComposerResources into a seperate
shared library. ComposerResources contains all of the
mapper code. composer@2.x-hal will depend on the new
composer@2.x-resource hal. Everyone downstream must
also add the composer@2.x-resource file now. However,
they will not be broken again when we add a new mapper
version.
Bug: 136016160
Test: Compiles and boots
Change-Id: I208a954a941ed65938074cd3efb8a6893a2bc1eb
diff --git a/graphics/composer/2.1/utils/resources/Android.bp b/graphics/composer/2.1/utils/resources/Android.bp
new file mode 100644
index 0000000..e7ba458
--- /dev/null
+++ b/graphics/composer/2.1/utils/resources/Android.bp
@@ -0,0 +1,49 @@
+//
+// Copyright (C) 2019 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.
+
+cc_library_shared {
+ name: "android.hardware.graphics.composer@2.1-resources",
+ defaults: ["hidl_defaults"],
+ vendor_available: true,
+ shared_libs: [
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
+ "libcutils",
+ "libhardware", // TODO remove hwcomposer2.h dependency
+ "libhidlbase",
+ "liblog",
+ "libutils",
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
+ "libhardware",
+ "libhidlbase",
+ "liblog",
+ "libutils",
+ ],
+ header_libs: [
+ "android.hardware.graphics.composer@2.1-command-buffer",
+ ],
+ export_header_lib_headers: [
+ "android.hardware.graphics.composer@2.1-command-buffer",
+ ],
+ export_include_dirs: ["include"],
+ srcs: [
+ "ComposerResources.cpp",
+ ],
+}
diff --git a/graphics/composer/2.1/utils/resources/ComposerResources.cpp b/graphics/composer/2.1/utils/resources/ComposerResources.cpp
new file mode 100644
index 0000000..d28eedc
--- /dev/null
+++ b/graphics/composer/2.1/utils/resources/ComposerResources.cpp
@@ -0,0 +1,485 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#define LOG_TAG "ComposerResources"
+
+#include "composer-resources/2.1/ComposerResources.h"
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+bool ComposerHandleImporter::init() {
+ mMapper3 = mapper::V3_0::IMapper::getService();
+ if (mMapper3) {
+ return true;
+ }
+ ALOGI_IF(!mMapper3, "failed to get mapper 3.0 service, falling back to mapper 2.0");
+
+ mMapper2 = mapper::V2_0::IMapper::getService();
+ ALOGE_IF(!mMapper2, "failed to get mapper 2.0 service");
+
+ return mMapper2 != nullptr;
+}
+
+Error ComposerHandleImporter::importBuffer(const native_handle_t* rawHandle,
+ const native_handle_t** outBufferHandle) {
+ if (!rawHandle || (!rawHandle->numFds && !rawHandle->numInts)) {
+ *outBufferHandle = nullptr;
+ return Error::NONE;
+ }
+
+ const native_handle_t* bufferHandle;
+ if (mMapper2) {
+ mapper::V2_0::Error error;
+ mMapper2->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) {
+ error = tmpError;
+ bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle);
+ });
+ if (error != mapper::V2_0::Error::NONE) {
+ return Error::NO_RESOURCES;
+ }
+ }
+ if (mMapper3) {
+ mapper::V3_0::Error error;
+ mMapper3->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) {
+ error = tmpError;
+ bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle);
+ });
+ if (error != mapper::V3_0::Error::NONE) {
+ return Error::NO_RESOURCES;
+ }
+ }
+
+ *outBufferHandle = bufferHandle;
+ return Error::NONE;
+}
+
+void ComposerHandleImporter::freeBuffer(const native_handle_t* bufferHandle) {
+ if (bufferHandle) {
+ if (mMapper2) {
+ mMapper2->freeBuffer(static_cast<void*>(const_cast<native_handle_t*>(bufferHandle)));
+ } else if (mMapper3) {
+ mMapper3->freeBuffer(static_cast<void*>(const_cast<native_handle_t*>(bufferHandle)));
+ }
+ }
+}
+
+Error ComposerHandleImporter::importStream(const native_handle_t* rawHandle,
+ const native_handle_t** outStreamHandle) {
+ const native_handle_t* streamHandle = nullptr;
+ if (rawHandle) {
+ streamHandle = native_handle_clone(rawHandle);
+ if (!streamHandle) {
+ return Error::NO_RESOURCES;
+ }
+ }
+
+ *outStreamHandle = streamHandle;
+ return Error::NONE;
+}
+
+void ComposerHandleImporter::freeStream(const native_handle_t* streamHandle) {
+ if (streamHandle) {
+ native_handle_close(streamHandle);
+ native_handle_delete(const_cast<native_handle_t*>(streamHandle));
+ }
+}
+
+ComposerHandleCache::ComposerHandleCache(ComposerHandleImporter& importer, HandleType type,
+ uint32_t cacheSize)
+ : mImporter(importer), mHandleType(type), mHandles(cacheSize, nullptr) {}
+
+// must be initialized later with initCache
+ComposerHandleCache::ComposerHandleCache(ComposerHandleImporter& importer) : mImporter(importer) {}
+
+ComposerHandleCache::~ComposerHandleCache() {
+ switch (mHandleType) {
+ case HandleType::BUFFER:
+ for (auto handle : mHandles) {
+ mImporter.freeBuffer(handle);
+ }
+ break;
+ case HandleType::STREAM:
+ for (auto handle : mHandles) {
+ mImporter.freeStream(handle);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+bool ComposerHandleCache::initCache(HandleType type, uint32_t cacheSize) {
+ // already initialized
+ if (mHandleType != HandleType::INVALID) {
+ return false;
+ }
+
+ mHandleType = type;
+ mHandles.resize(cacheSize, nullptr);
+
+ return true;
+}
+
+Error ComposerHandleCache::lookupCache(uint32_t slot, const native_handle_t** outHandle) {
+ if (slot >= 0 && slot < mHandles.size()) {
+ *outHandle = mHandles[slot];
+ return Error::NONE;
+ } else {
+ return Error::BAD_PARAMETER;
+ }
+}
+
+Error ComposerHandleCache::updateCache(uint32_t slot, const native_handle_t* handle,
+ const native_handle** outReplacedHandle) {
+ if (slot >= 0 && slot < mHandles.size()) {
+ auto& cachedHandle = mHandles[slot];
+ *outReplacedHandle = cachedHandle;
+ cachedHandle = handle;
+ return Error::NONE;
+ } else {
+ return Error::BAD_PARAMETER;
+ }
+}
+
+// when fromCache is true, look up in the cache; otherwise, update the cache
+Error ComposerHandleCache::getHandle(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+ const native_handle_t** outHandle,
+ const native_handle** outReplacedHandle) {
+ if (fromCache) {
+ *outReplacedHandle = nullptr;
+ return lookupCache(slot, outHandle);
+ } else {
+ *outHandle = inHandle;
+ return updateCache(slot, inHandle, outReplacedHandle);
+ }
+}
+
+ComposerLayerResource::ComposerLayerResource(ComposerHandleImporter& importer,
+ uint32_t bufferCacheSize)
+ : mBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, bufferCacheSize),
+ mSidebandStreamCache(importer, ComposerHandleCache::HandleType::STREAM, 1) {}
+
+Error ComposerLayerResource::getBuffer(uint32_t slot, bool fromCache,
+ const native_handle_t* inHandle,
+ const native_handle_t** outHandle,
+ const native_handle** outReplacedHandle) {
+ return mBufferCache.getHandle(slot, fromCache, inHandle, outHandle, outReplacedHandle);
+}
+
+Error ComposerLayerResource::getSidebandStream(uint32_t slot, bool fromCache,
+ const native_handle_t* inHandle,
+ const native_handle_t** outHandle,
+ const native_handle** outReplacedHandle) {
+ return mSidebandStreamCache.getHandle(slot, fromCache, inHandle, outHandle, outReplacedHandle);
+}
+
+ComposerDisplayResource::ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer,
+ uint32_t outputBufferCacheSize)
+ : mType(type),
+ mClientTargetCache(importer),
+ mOutputBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, outputBufferCacheSize),
+ mMustValidate(true) {}
+
+bool ComposerDisplayResource::initClientTargetCache(uint32_t cacheSize) {
+ return mClientTargetCache.initCache(ComposerHandleCache::HandleType::BUFFER, cacheSize);
+}
+
+bool ComposerDisplayResource::isVirtual() const {
+ return mType == DisplayType::VIRTUAL;
+}
+
+Error ComposerDisplayResource::getClientTarget(uint32_t slot, bool fromCache,
+ const native_handle_t* inHandle,
+ const native_handle_t** outHandle,
+ const native_handle** outReplacedHandle) {
+ return mClientTargetCache.getHandle(slot, fromCache, inHandle, outHandle, outReplacedHandle);
+}
+
+Error ComposerDisplayResource::getOutputBuffer(uint32_t slot, bool fromCache,
+ const native_handle_t* inHandle,
+ const native_handle_t** outHandle,
+ const native_handle** outReplacedHandle) {
+ return mOutputBufferCache.getHandle(slot, fromCache, inHandle, outHandle, outReplacedHandle);
+}
+
+bool ComposerDisplayResource::addLayer(Layer layer,
+ std::unique_ptr<ComposerLayerResource> layerResource) {
+ auto result = mLayerResources.emplace(layer, std::move(layerResource));
+ return result.second;
+}
+
+bool ComposerDisplayResource::removeLayer(Layer layer) {
+ return mLayerResources.erase(layer) > 0;
+}
+
+ComposerLayerResource* ComposerDisplayResource::findLayerResource(Layer layer) {
+ auto layerIter = mLayerResources.find(layer);
+ if (layerIter == mLayerResources.end()) {
+ return nullptr;
+ }
+
+ return layerIter->second.get();
+}
+
+std::vector<Layer> ComposerDisplayResource::getLayers() const {
+ std::vector<Layer> layers;
+ layers.reserve(mLayerResources.size());
+ for (const auto& layerKey : mLayerResources) {
+ layers.push_back(layerKey.first);
+ }
+ return layers;
+}
+
+void ComposerDisplayResource::setMustValidateState(bool mustValidate) {
+ mMustValidate = mustValidate;
+}
+
+bool ComposerDisplayResource::mustValidate() const {
+ return mMustValidate;
+}
+
+std::unique_ptr<ComposerResources> ComposerResources::create() {
+ auto resources = std::make_unique<ComposerResources>();
+ return resources->init() ? std::move(resources) : nullptr;
+}
+
+bool ComposerResources::init() {
+ return mImporter.init();
+}
+
+void ComposerResources::clear(RemoveDisplay removeDisplay) {
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ for (const auto& displayKey : mDisplayResources) {
+ Display display = displayKey.first;
+ const ComposerDisplayResource& displayResource = *displayKey.second;
+ removeDisplay(display, displayResource.isVirtual(), displayResource.getLayers());
+ }
+ mDisplayResources.clear();
+}
+
+Error ComposerResources::addPhysicalDisplay(Display display) {
+ auto displayResource = createDisplayResource(ComposerDisplayResource::DisplayType::PHYSICAL, 0);
+
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ auto result = mDisplayResources.emplace(display, std::move(displayResource));
+ return result.second ? Error::NONE : Error::BAD_DISPLAY;
+}
+
+Error ComposerResources::addVirtualDisplay(Display display, uint32_t outputBufferCacheSize) {
+ auto displayResource = createDisplayResource(ComposerDisplayResource::DisplayType::VIRTUAL,
+ outputBufferCacheSize);
+
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ auto result = mDisplayResources.emplace(display, std::move(displayResource));
+ return result.second ? Error::NONE : Error::BAD_DISPLAY;
+}
+
+Error ComposerResources::removeDisplay(Display display) {
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ return mDisplayResources.erase(display) > 0 ? Error::NONE : Error::BAD_DISPLAY;
+}
+
+Error ComposerResources::setDisplayClientTargetCacheSize(Display display,
+ uint32_t clientTargetCacheSize) {
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
+ if (!displayResource) {
+ return Error::BAD_DISPLAY;
+ }
+
+ return displayResource->initClientTargetCache(clientTargetCacheSize) ? Error::NONE
+ : Error::BAD_PARAMETER;
+}
+
+Error ComposerResources::addLayer(Display display, Layer layer, uint32_t bufferCacheSize) {
+ auto layerResource = createLayerResource(bufferCacheSize);
+
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
+ if (!displayResource) {
+ return Error::BAD_DISPLAY;
+ }
+
+ return displayResource->addLayer(layer, std::move(layerResource)) ? Error::NONE
+ : Error::BAD_LAYER;
+}
+
+Error ComposerResources::removeLayer(Display display, Layer layer) {
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
+ if (!displayResource) {
+ return Error::BAD_DISPLAY;
+ }
+
+ return displayResource->removeLayer(layer) ? Error::NONE : Error::BAD_LAYER;
+}
+
+Error ComposerResources::getDisplayClientTarget(Display display, uint32_t slot, bool fromCache,
+ const native_handle_t* rawHandle,
+ const native_handle_t** outBufferHandle,
+ ReplacedHandle* outReplacedBuffer) {
+ return getHandle(display, 0, slot, Cache::CLIENT_TARGET, fromCache, rawHandle, outBufferHandle,
+ outReplacedBuffer);
+}
+
+Error ComposerResources::getDisplayOutputBuffer(Display display, uint32_t slot, bool fromCache,
+ const native_handle_t* rawHandle,
+ const native_handle_t** outBufferHandle,
+ ReplacedHandle* outReplacedBuffer) {
+ return getHandle(display, 0, slot, Cache::OUTPUT_BUFFER, fromCache, rawHandle, outBufferHandle,
+ outReplacedBuffer);
+}
+
+Error ComposerResources::getLayerBuffer(Display display, Layer layer, uint32_t slot, bool fromCache,
+ const native_handle_t* rawHandle,
+ const native_handle_t** outBufferHandle,
+ ReplacedHandle* outReplacedBuffer) {
+ return getHandle(display, layer, slot, Cache::LAYER_BUFFER, fromCache, rawHandle,
+ outBufferHandle, outReplacedBuffer);
+}
+
+Error ComposerResources::getLayerSidebandStream(Display display, Layer layer,
+ const native_handle_t* rawHandle,
+ const native_handle_t** outStreamHandle,
+ ReplacedHandle* outReplacedStream) {
+ return getHandle(display, layer, 0, Cache::LAYER_SIDEBAND_STREAM, false, rawHandle,
+ outStreamHandle, outReplacedStream);
+}
+
+void ComposerResources::setDisplayMustValidateState(Display display, bool mustValidate) {
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ auto* displayResource = findDisplayResourceLocked(display);
+ if (displayResource) {
+ displayResource->setMustValidateState(mustValidate);
+ }
+}
+
+bool ComposerResources::mustValidateDisplay(Display display) {
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ auto* displayResource = findDisplayResourceLocked(display);
+ if (displayResource) {
+ return displayResource->mustValidate();
+ }
+ return false;
+}
+
+std::unique_ptr<ComposerDisplayResource> ComposerResources::createDisplayResource(
+ ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) {
+ return std::make_unique<ComposerDisplayResource>(type, mImporter, outputBufferCacheSize);
+}
+
+std::unique_ptr<ComposerLayerResource> ComposerResources::createLayerResource(
+ uint32_t bufferCacheSize) {
+ return std::make_unique<ComposerLayerResource>(mImporter, bufferCacheSize);
+}
+
+ComposerDisplayResource* ComposerResources::findDisplayResourceLocked(Display display) {
+ auto iter = mDisplayResources.find(display);
+ if (iter == mDisplayResources.end()) {
+ return nullptr;
+ }
+ return iter->second.get();
+}
+
+Error ComposerResources::getHandle(Display display, Layer layer, uint32_t slot, Cache cache,
+ bool fromCache, const native_handle_t* rawHandle,
+ const native_handle_t** outHandle,
+ ReplacedHandle* outReplacedHandle) {
+ Error error;
+
+ // import the raw handle (or ignore raw handle when fromCache is true)
+ const native_handle_t* importedHandle = nullptr;
+ if (!fromCache) {
+ error = (outReplacedHandle->isBuffer())
+ ? mImporter.importBuffer(rawHandle, &importedHandle)
+ : mImporter.importStream(rawHandle, &importedHandle);
+ if (error != Error::NONE) {
+ return error;
+ }
+ }
+
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+
+ // find display/layer resource
+ const bool needLayerResource = (cache == ComposerResources::Cache::LAYER_BUFFER ||
+ cache == ComposerResources::Cache::LAYER_SIDEBAND_STREAM);
+ ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
+ ComposerLayerResource* layerResource = (displayResource && needLayerResource)
+ ? displayResource->findLayerResource(layer)
+ : nullptr;
+
+ // lookup or update cache
+ const native_handle_t* replacedHandle = nullptr;
+ if (displayResource && (!needLayerResource || layerResource)) {
+ switch (cache) {
+ case ComposerResources::Cache::CLIENT_TARGET:
+ error = displayResource->getClientTarget(slot, fromCache, importedHandle, outHandle,
+ &replacedHandle);
+ break;
+ case ComposerResources::Cache::OUTPUT_BUFFER:
+ error = displayResource->getOutputBuffer(slot, fromCache, importedHandle, outHandle,
+ &replacedHandle);
+ break;
+ case ComposerResources::Cache::LAYER_BUFFER:
+ error = layerResource->getBuffer(slot, fromCache, importedHandle, outHandle,
+ &replacedHandle);
+ break;
+ case ComposerResources::Cache::LAYER_SIDEBAND_STREAM:
+ error = layerResource->getSidebandStream(slot, fromCache, importedHandle, outHandle,
+ &replacedHandle);
+ break;
+ default:
+ error = Error::BAD_PARAMETER;
+ break;
+ }
+
+ if (error != Error::NONE) {
+ ALOGW("invalid cache %d slot %d", int(cache), int(slot));
+ }
+ } else if (!displayResource) {
+ error = Error::BAD_DISPLAY;
+ } else {
+ error = Error::BAD_LAYER;
+ }
+
+ // clean up on errors
+ if (error != Error::NONE) {
+ if (!fromCache) {
+ if (outReplacedHandle->isBuffer()) {
+ mImporter.freeBuffer(importedHandle);
+ } else {
+ mImporter.freeStream(importedHandle);
+ }
+ }
+ return error;
+ }
+
+ outReplacedHandle->reset(&mImporter, replacedHandle);
+
+ return Error::NONE;
+}
+
+} // namespace hal
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h b/graphics/composer/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h
new file mode 100644
index 0000000..b9b7138
--- /dev/null
+++ b/graphics/composer/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h
@@ -0,0 +1,258 @@
+/*
+ * Copyright 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
+
+#ifndef LOG_TAG
+#warning "ComposerResources.h included without LOG_TAG"
+#endif
+
+#include <memory>
+#include <mutex>
+#include <unordered_map>
+#include <vector>
+
+#include <android/hardware/graphics/composer/2.1/types.h>
+
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <android/hardware/graphics/mapper/3.0/IMapper.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+// wrapper for IMapper to import buffers and sideband streams
+class ComposerHandleImporter {
+ public:
+ bool init();
+
+ Error importBuffer(const native_handle_t* rawHandle, const native_handle_t** outBufferHandle);
+ void freeBuffer(const native_handle_t* bufferHandle);
+ Error importStream(const native_handle_t* rawHandle, const native_handle_t** outStreamHandle);
+ void freeStream(const native_handle_t* streamHandle);
+
+ private:
+ sp<mapper::V2_0::IMapper> mMapper2;
+ sp<mapper::V3_0::IMapper> mMapper3;
+};
+
+class ComposerHandleCache {
+ public:
+ enum class HandleType {
+ INVALID,
+ BUFFER,
+ STREAM,
+ };
+
+ ComposerHandleCache(ComposerHandleImporter& importer, HandleType type, uint32_t cacheSize);
+
+ // must be initialized later with initCache
+ ComposerHandleCache(ComposerHandleImporter& importer);
+
+ ~ComposerHandleCache();
+
+ ComposerHandleCache(const ComposerHandleCache&) = delete;
+ ComposerHandleCache& operator=(const ComposerHandleCache&) = delete;
+
+ bool initCache(HandleType type, uint32_t cacheSize);
+ Error lookupCache(uint32_t slot, const native_handle_t** outHandle);
+ Error updateCache(uint32_t slot, const native_handle_t* handle,
+ const native_handle** outReplacedHandle);
+
+ // when fromCache is true, look up in the cache; otherwise, update the cache
+ Error getHandle(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+ const native_handle_t** outHandle, const native_handle** outReplacedHandle);
+
+ private:
+ ComposerHandleImporter& mImporter;
+ HandleType mHandleType = HandleType::INVALID;
+ std::vector<const native_handle_t*> mHandles;
+};
+
+// layer resource
+class ComposerLayerResource {
+ public:
+ ComposerLayerResource(ComposerHandleImporter& importer, uint32_t bufferCacheSize);
+
+ virtual ~ComposerLayerResource() = default;
+
+ Error getBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+ const native_handle_t** outHandle, const native_handle** outReplacedHandle);
+ Error getSidebandStream(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+ const native_handle_t** outHandle,
+ const native_handle** outReplacedHandle);
+
+ protected:
+ ComposerHandleCache mBufferCache;
+ ComposerHandleCache mSidebandStreamCache;
+};
+
+// display resource
+class ComposerDisplayResource {
+ public:
+ enum class DisplayType {
+ PHYSICAL,
+ VIRTUAL,
+ };
+
+ virtual ~ComposerDisplayResource() = default;
+
+ ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer,
+ uint32_t outputBufferCacheSize);
+
+ bool initClientTargetCache(uint32_t cacheSize);
+
+ bool isVirtual() const;
+
+ Error getClientTarget(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+ const native_handle_t** outHandle,
+ const native_handle** outReplacedHandle);
+
+ Error getOutputBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+ const native_handle_t** outHandle,
+ const native_handle** outReplacedHandle);
+
+ bool addLayer(Layer layer, std::unique_ptr<ComposerLayerResource> layerResource);
+ bool removeLayer(Layer layer);
+ ComposerLayerResource* findLayerResource(Layer layer);
+ std::vector<Layer> getLayers() const;
+
+ void setMustValidateState(bool mustValidate);
+
+ bool mustValidate() const;
+
+ protected:
+ const DisplayType mType;
+ ComposerHandleCache mClientTargetCache;
+ ComposerHandleCache mOutputBufferCache;
+ bool mMustValidate;
+
+ std::unordered_map<Layer, std::unique_ptr<ComposerLayerResource>> mLayerResources;
+};
+
+class ComposerResources {
+ public:
+ static std::unique_ptr<ComposerResources> create();
+
+ ComposerResources() = default;
+ virtual ~ComposerResources() = default;
+
+ bool init();
+
+ using RemoveDisplay =
+ std::function<void(Display display, bool isVirtual, const std::vector<Layer>& layers)>;
+ void clear(RemoveDisplay removeDisplay);
+
+ Error addPhysicalDisplay(Display display);
+ Error addVirtualDisplay(Display display, uint32_t outputBufferCacheSize);
+
+ Error removeDisplay(Display display);
+
+ Error setDisplayClientTargetCacheSize(Display display, uint32_t clientTargetCacheSize);
+
+ Error addLayer(Display display, Layer layer, uint32_t bufferCacheSize);
+ Error removeLayer(Display display, Layer layer);
+
+ void setDisplayMustValidateState(Display display, bool mustValidate);
+
+ bool mustValidateDisplay(Display display);
+
+ // When a buffer in the cache is replaced by a new one, we must keep it
+ // alive until it has been replaced in ComposerHal.
+ class ReplacedHandle {
+ public:
+ explicit ReplacedHandle(bool isBuffer) : mIsBuffer(isBuffer) {}
+ ReplacedHandle(const ReplacedHandle&) = delete;
+ ReplacedHandle& operator=(const ReplacedHandle&) = delete;
+
+ ~ReplacedHandle() { reset(); }
+
+ bool isBuffer() { return mIsBuffer; }
+
+ void reset(ComposerHandleImporter* importer = nullptr,
+ const native_handle_t* handle = nullptr) {
+ if (mHandle) {
+ if (mIsBuffer) {
+ mImporter->freeBuffer(mHandle);
+ } else {
+ mImporter->freeStream(mHandle);
+ }
+ }
+
+ mImporter = importer;
+ mHandle = handle;
+ }
+
+ private:
+ bool mIsBuffer;
+ ComposerHandleImporter* mImporter = nullptr;
+ const native_handle_t* mHandle = nullptr;
+ };
+
+ Error getDisplayClientTarget(Display display, uint32_t slot, bool fromCache,
+ const native_handle_t* rawHandle,
+ const native_handle_t** outBufferHandle,
+ ReplacedHandle* outReplacedBuffer);
+
+ Error getDisplayOutputBuffer(Display display, uint32_t slot, bool fromCache,
+ const native_handle_t* rawHandle,
+ const native_handle_t** outBufferHandle,
+ ReplacedHandle* outReplacedBuffer);
+
+ Error getLayerBuffer(Display display, Layer layer, uint32_t slot, bool fromCache,
+ const native_handle_t* rawHandle, const native_handle_t** outBufferHandle,
+ ReplacedHandle* outReplacedBuffer);
+
+ Error getLayerSidebandStream(Display display, Layer layer, const native_handle_t* rawHandle,
+ const native_handle_t** outStreamHandle,
+ ReplacedHandle* outReplacedStream);
+
+ protected:
+ virtual std::unique_ptr<ComposerDisplayResource> createDisplayResource(
+ ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize);
+
+ virtual std::unique_ptr<ComposerLayerResource> createLayerResource(uint32_t bufferCacheSize);
+
+ ComposerDisplayResource* findDisplayResourceLocked(Display display);
+
+ ComposerHandleImporter mImporter;
+
+ std::mutex mDisplayResourcesMutex;
+ std::unordered_map<Display, std::unique_ptr<ComposerDisplayResource>> mDisplayResources;
+
+ private:
+ enum class Cache {
+ CLIENT_TARGET,
+ OUTPUT_BUFFER,
+ LAYER_BUFFER,
+ LAYER_SIDEBAND_STREAM,
+ };
+
+ Error getHandle(Display display, Layer layer, uint32_t slot, Cache cache, bool fromCache,
+ const native_handle_t* rawHandle, const native_handle_t** outHandle,
+ ReplacedHandle* outReplacedHandle);
+};
+
+} // namespace hal
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android