1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <cstdint> 20 #include <stack> 21 #include <unordered_map> 22 23 // TODO(b/129481165): remove the #pragma below and fix conversion issues 24 #pragma clang diagnostic push 25 #pragma clang diagnostic ignored "-Wconversion" 26 #pragma clang diagnostic ignored "-Wextra" 27 28 #include <gui/BufferQueue.h> 29 30 // TODO(b/129481165): remove the #pragma below and fix conversion issues 31 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra" 32 33 #include <utils/StrongPointer.h> 34 35 namespace android { 36 37 class GraphicBuffer; 38 39 namespace compositionengine::impl { 40 41 // The buffer cache returns both a slot and the buffer that should be sent to HWC. In cases 42 // where the buffer is already cached, the buffer is a nullptr and will not be sent to HWC as 43 // an optimization. 44 struct HwcSlotAndBuffer { 45 uint32_t slot; 46 sp<GraphicBuffer> buffer; 47 }; 48 49 // 50 // Manages the slot assignments for a buffers stored in Composer HAL's cache. 51 // 52 // Cache slots are an optimization when communicating buffer handles to Composer 53 // HAL. When updating a layer's buffer, we can either send a new buffer handle 54 // along with it's slot assignment or request the HAL to reuse a buffer handle 55 // that we've already sent by using the slot assignment. The latter is cheaper 56 // since it eliminates the overhead to transfer the buffer handle over IPC and 57 // the overhead for the HAL to clone the handle. 58 // 59 class HwcBufferCache { 60 private: 61 static const constexpr size_t kMaxLayerBufferCount = BufferQueue::NUM_BUFFER_SLOTS; 62 63 public: 64 // public for testing 65 // Override buffers don't use the normal cache slots because we don't want them to evict client 66 // buffers from the cache. We add an extra slot at the end for the override buffers. 67 static const constexpr size_t kOverrideBufferSlot = kMaxLayerBufferCount; 68 69 HwcBufferCache(); 70 71 // 72 // Given a buffer, return the HWC cache slot and buffer to send to HWC. 73 // 74 // If the buffer is already in the cache, the buffer is null to optimize away sending HWC the 75 // buffer handle. 76 // 77 HwcSlotAndBuffer getHwcSlotAndBuffer(const sp<GraphicBuffer>& buffer); 78 // 79 // Given a buffer, return the HWC cache slot and buffer to send to HWC. 80 // 81 // A special slot number is used for override buffers. 82 // 83 // If the buffer is already in the cache, the buffer is null to optimize away sending HWC the 84 // buffer handle. 85 // 86 HwcSlotAndBuffer getOverrideHwcSlotAndBuffer(const sp<GraphicBuffer>& buffer); 87 88 // 89 // When a client process discards a buffer, it needs to be purged from the HWC cache. 90 // 91 // Returns the slot number of the buffer, or UINT32_MAX if it wasn't found in the cache. 92 // 93 uint32_t uncache(uint64_t graphicBufferId); 94 95 private: 96 uint32_t cache(const sp<GraphicBuffer>& buffer); 97 uint32_t getLeastRecentlyUsedSlot(); 98 99 struct Cache { 100 sp<GraphicBuffer> buffer; 101 uint32_t slot; 102 // Cache entries are evicted according to least-recently-used when more than 103 // kMaxLayerBufferCount unique buffers have been sent to a layer. 104 uint64_t lruCounter; 105 }; 106 107 std::unordered_map<uint64_t, Cache> mCacheByBufferId; 108 sp<GraphicBuffer> mLastOverrideBuffer; 109 std::stack<uint32_t> mFreeSlots; 110 uint64_t mLeastRecentlyUsedCounter; 111 }; 112 113 } // namespace compositionengine::impl 114 } // namespace android 115