blob: f5ab35067d2e1afa76f5fbd83ba296a421e43c55 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "garnet/bin/ui/sketchy/buffer/shared_buffer_pool.h"
#include <cmath>
namespace {
constexpr uint32_t kBaseBufferPower = 10;
} // namespace
namespace sketchy_service {
SharedBufferPool::SharedBufferPool(scenic::Session* session,
escher::BufferFactory* factory)
: session_(session), buffer_factory_(factory), weak_factory_(this) {}
SharedBufferPtr SharedBufferPool::GetBuffer(vk::DeviceSize capacity_req) {
SharedBufferPtr buffer;
auto capacity = GetBufferKey(capacity_req);
if (!free_buffers_[capacity].empty()) {
buffer = std::move(free_buffers_[capacity].back());
free_buffers_[capacity].pop_back();
} else {
buffer = SharedBuffer::New(session_, buffer_factory_, capacity);
}
used_buffers_.insert(buffer);
return buffer;
}
void SharedBufferPool::ReturnBuffer(SharedBufferPtr buffer,
zx::event release_fence) {
if (used_buffers_.find(buffer) == used_buffers_.end()) {
FXL_DLOG(WARNING) << "buffer(" << buffer.get()
<< ") does not come from pool(" << this << ")";
return;
}
// Listen to the fence release event from scenic, when the first subsequent
// frame takes effect in Scenic. Once it's released, recycle it. This should
// be done in ReturnBuffer() instead of GetBuffer(), because otherwise, we
// will miss the release signals for the frames that come after.
auto pair = fence_listeners_.insert(
std::make_unique<escher::FenceListener>(std::move(release_fence)));
auto fence_listener = pair.first;
(*fence_listener)
->WaitReadyAsync(
[weak = weak_factory_.GetWeakPtr(), fence_listener, buffer] {
if (weak) {
weak->fence_listeners_.erase(fence_listener);
weak->RecycleBuffer(buffer);
}
});
}
void SharedBufferPool::RecycleBuffer(SharedBufferPtr buffer) {
buffer->Reset();
auto capacity = buffer->capacity();
FXL_DCHECK(capacity == GetBufferKey(capacity));
free_buffers_[capacity].push_back(std::move(buffer));
}
vk::DeviceSize SharedBufferPool::GetBufferKey(vk::DeviceSize capacity_req) {
capacity_req = std::max(1UL, capacity_req);
uint32_t power = static_cast<uint32_t>(std::ceil(std::log2(capacity_req)));
return 1U << std::max(kBaseBufferPower, power);
}
} // namespace sketchy_service