/* * 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. */ #pragma once #include #include #include // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" #pragma clang diagnostic ignored "-Wextra" #include // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic pop // ignored "-Wconversion -Wextra" #include namespace android { class GraphicBuffer; namespace compositionengine::impl { // The buffer cache returns both a slot and the buffer that should be sent to HWC. In cases // where the buffer is already cached, the buffer is a nullptr and will not be sent to HWC as // an optimization. struct HwcSlotAndBuffer { uint32_t slot; sp buffer; }; // // Manages the slot assignments for a buffers stored in Composer HAL's cache. // // Cache slots are an optimization when communicating buffer handles to Composer // HAL. When updating a layer's buffer, we can either send a new buffer handle // along with it's slot assignment or request the HAL to reuse a buffer handle // that we've already sent by using the slot assignment. The latter is cheaper // since it eliminates the overhead to transfer the buffer handle over IPC and // the overhead for the HAL to clone the handle. // class HwcBufferCache { private: static const constexpr size_t kMaxLayerBufferCount = BufferQueue::NUM_BUFFER_SLOTS; public: // public for testing // Override buffers don't use the normal cache slots because we don't want them to evict client // buffers from the cache. We add an extra slot at the end for the override buffers. static const constexpr size_t kOverrideBufferSlot = kMaxLayerBufferCount; HwcBufferCache(); // // Given a buffer, return the HWC cache slot and buffer to send to HWC. // // If the buffer is already in the cache, the buffer is null to optimize away sending HWC the // buffer handle. // HwcSlotAndBuffer getHwcSlotAndBuffer(const sp& buffer); // // Given a buffer, return the HWC cache slot and buffer to send to HWC. // // A special slot number is used for override buffers. // // If the buffer is already in the cache, the buffer is null to optimize away sending HWC the // buffer handle. // HwcSlotAndBuffer getOverrideHwcSlotAndBuffer(const sp& buffer); // // When a client process discards a buffer, it needs to be purged from the HWC cache. // // Returns the slot number of the buffer, or UINT32_MAX if it wasn't found in the cache. // uint32_t uncache(uint64_t graphicBufferId); private: uint32_t cache(const sp& buffer); uint32_t getLeastRecentlyUsedSlot(); struct Cache { sp buffer; uint32_t slot; // Cache entries are evicted according to least-recently-used when more than // kMaxLayerBufferCount unique buffers have been sent to a layer. uint64_t lruCounter; }; std::unordered_map mCacheByBufferId; sp mLastOverrideBuffer; std::stack mFreeSlots; uint64_t mLeastRecentlyUsedCounter; }; } // namespace compositionengine::impl } // namespace android