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