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 #include <compositionengine/impl/HwcBufferCache.h> 18 19 #include <gui/BufferQueue.h> 20 #include <ui/GraphicBuffer.h> 21 22 namespace android::compositionengine::impl { 23 HwcBufferCache()24HwcBufferCache::HwcBufferCache() { 25 for (uint32_t i = kMaxLayerBufferCount; i-- > 0;) { 26 mFreeSlots.push(i); 27 } 28 } 29 getHwcSlotAndBuffer(const sp<GraphicBuffer> & buffer)30HwcSlotAndBuffer HwcBufferCache::getHwcSlotAndBuffer(const sp<GraphicBuffer>& buffer) { 31 if (auto i = mCacheByBufferId.find(buffer->getId()); i != mCacheByBufferId.end()) { 32 Cache& cache = i->second; 33 // mark this cache slot as more recently used so it won't get evicted anytime soon 34 cache.lruCounter = mLeastRecentlyUsedCounter++; 35 return {cache.slot, nullptr}; 36 } 37 return {cache(buffer), buffer}; 38 } 39 getOverrideHwcSlotAndBuffer(const sp<GraphicBuffer> & buffer)40HwcSlotAndBuffer HwcBufferCache::getOverrideHwcSlotAndBuffer(const sp<GraphicBuffer>& buffer) { 41 if (buffer == mLastOverrideBuffer) { 42 return {kOverrideBufferSlot, nullptr}; 43 } 44 mLastOverrideBuffer = buffer; 45 return {kOverrideBufferSlot, buffer}; 46 } 47 uncache(uint64_t bufferId)48uint32_t HwcBufferCache::uncache(uint64_t bufferId) { 49 if (auto i = mCacheByBufferId.find(bufferId); i != mCacheByBufferId.end()) { 50 uint32_t slot = i->second.slot; 51 mCacheByBufferId.erase(i); 52 mFreeSlots.push(slot); 53 return slot; 54 } 55 if (mLastOverrideBuffer && bufferId == mLastOverrideBuffer->getId()) { 56 mLastOverrideBuffer = nullptr; 57 return kOverrideBufferSlot; 58 } 59 return UINT32_MAX; 60 } 61 cache(const sp<GraphicBuffer> & buffer)62uint32_t HwcBufferCache::cache(const sp<GraphicBuffer>& buffer) { 63 Cache cache; 64 cache.slot = getLeastRecentlyUsedSlot(); 65 cache.lruCounter = mLeastRecentlyUsedCounter++; 66 cache.buffer = buffer; 67 mCacheByBufferId.emplace(buffer->getId(), cache); 68 return cache.slot; 69 } 70 getLeastRecentlyUsedSlot()71uint32_t HwcBufferCache::getLeastRecentlyUsedSlot() { 72 if (mFreeSlots.empty()) { 73 assert(!mCacheByBufferId.empty()); 74 // evict the least recently used cache entry 75 auto cacheToErase = mCacheByBufferId.begin(); 76 for (auto i = cacheToErase; i != mCacheByBufferId.end(); ++i) { 77 if (i->second.lruCounter < cacheToErase->second.lruCounter) { 78 cacheToErase = i; 79 } 80 } 81 uint32_t slot = cacheToErase->second.slot; 82 mCacheByBufferId.erase(cacheToErase); 83 mFreeSlots.push(slot); 84 } 85 uint32_t slot = mFreeSlots.top(); 86 mFreeSlots.pop(); 87 return slot; 88 } 89 90 } // namespace android::compositionengine::impl 91