mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
This wires up Android Hardware Buffer backed swapchains on platform that support it (Android >= 29) with a KHR swapchain fallback (which can be removed later to save on some binary size if needed). Some salient features of these swapchains and their differences with the KHR variant: * All swapchain images are guaranteed to R8G8B8A8. This could potentially allow for earlier creation of the context and the PSO libraries. * All swapchain allocations are lazy. This should greatly reduce the time it takes to create and resize a swapchain. However, swapchain image acquisition may take longer for the first few frame where there is no pre-pooled image available. Resizes should be similarly faster since the swapchain images for the intermediate sizes are never created. * Swapchain transients allocations (the attachments for the root render target) are also lazily allocated. * Swapchain images are pool and reused. The size of the pool is user specified (currently 2). If an image in the pool ages past a user supplied value (currently 1 second), it is collected as well. Applications that don't render frames for a long period of time should see less memory use because of swapchain image allocations. * The present mode of AHB swapchains behave similar to KHR swapchains but with VK_PRESENT_MODE_MAILBOX_KHR. In cases where there is no application managed frame pipelining, this might cause images to never be presented if a newer image is available. This wasted work can only be avoided by application provided pipelining. * There are no client side waits during image presentation. Instead, a new type of fence is wired up that exports its state as a sync file descriptor. The fence signal operation is enqueued on the client side and the buffer is set on the surface control. The presentation engine then performs the wait. * On Qualcomm devices, Chromium seems to be setting vendor specified flags for opting the hardware buffers into using UBWC. AFAICT, this is similar to AFBC (and NOT AFRC) on ARM Mali. This has not been wired up since I don't have a Qualcomm device at the moment and cant verify bandwidth use using GPU counters. I would also like to verify that UBWC is safe to use to images that can be used as input attachments.
78 lines
2.2 KiB
C++
78 lines
2.2 KiB
C++
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef FLUTTER_FML_CLOSURE_H_
|
|
#define FLUTTER_FML_CLOSURE_H_
|
|
|
|
#include <functional>
|
|
|
|
#include "flutter/fml/macros.h"
|
|
|
|
namespace fml {
|
|
|
|
using closure = std::function<void()>;
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// @brief Wraps a closure that is invoked in the destructor unless
|
|
/// released by the caller.
|
|
///
|
|
/// This is especially useful in dealing with APIs that return a
|
|
/// resource by accepting ownership of a sub-resource and a closure
|
|
/// that releases that resource. When such APIs are chained, each
|
|
/// link in the chain must check that the next member in the chain
|
|
/// has accepted the resource. If not, it must invoke the closure
|
|
/// eagerly. Not doing this results in a resource leak in the
|
|
/// erroneous case. Using this wrapper, the closure can be released
|
|
/// once the next call in the chain has successfully accepted
|
|
/// ownership of the resource. If not, the closure gets invoked
|
|
/// automatically at the end of the scope. This covers the cases
|
|
/// where there are early returns as well.
|
|
///
|
|
class ScopedCleanupClosure final {
|
|
public:
|
|
ScopedCleanupClosure() = default;
|
|
|
|
ScopedCleanupClosure(ScopedCleanupClosure&& other) {
|
|
closure_ = other.Release();
|
|
}
|
|
|
|
ScopedCleanupClosure& operator=(ScopedCleanupClosure&& other) {
|
|
closure_ = other.Release();
|
|
return *this;
|
|
}
|
|
|
|
explicit ScopedCleanupClosure(const fml::closure& closure)
|
|
: closure_(closure) {}
|
|
|
|
~ScopedCleanupClosure() { Reset(); }
|
|
|
|
fml::closure SetClosure(const fml::closure& closure) {
|
|
auto old_closure = closure_;
|
|
closure_ = closure;
|
|
return old_closure;
|
|
}
|
|
|
|
fml::closure Release() {
|
|
fml::closure closure = closure_;
|
|
closure_ = nullptr;
|
|
return closure;
|
|
}
|
|
|
|
void Reset() {
|
|
if (closure_) {
|
|
closure_();
|
|
closure_ = nullptr;
|
|
}
|
|
}
|
|
|
|
private:
|
|
fml::closure closure_;
|
|
|
|
FML_DISALLOW_COPY_AND_ASSIGN(ScopedCleanupClosure);
|
|
};
|
|
|
|
} // namespace fml
|
|
|
|
#endif // FLUTTER_FML_CLOSURE_H_
|