mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
145 lines
4.9 KiB
C++
145 lines
4.9 KiB
C++
// Copyright 2017 The Chromium 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_CONTENT_HANDLER_VULKAN_RASTERIZER_H_
|
|
#define FLUTTER_CONTENT_HANDLER_VULKAN_RASTERIZER_H_
|
|
|
|
#include <memory>
|
|
#include <queue>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
#include "apps/mozart/services/buffers/cpp/buffer_producer.h"
|
|
#include "flutter/content_handler/rasterizer.h"
|
|
#include "flutter/flow/compositor_context.h"
|
|
#include "flutter/vulkan/vulkan_application.h"
|
|
#include "flutter/vulkan/vulkan_device.h"
|
|
#include "lib/ftl/macros.h"
|
|
#include "third_party/skia/include/gpu/vk/GrVkBackendContext.h"
|
|
|
|
namespace flutter_runner {
|
|
|
|
class VulkanRasterizer : public Rasterizer {
|
|
public:
|
|
VulkanRasterizer();
|
|
|
|
~VulkanRasterizer() override;
|
|
|
|
bool IsValid() const;
|
|
|
|
void SetScene(fidl::InterfaceHandle<mozart::Scene> scene) override;
|
|
|
|
void Draw(std::unique_ptr<flow::LayerTree> layer_tree,
|
|
ftl::Closure callback) override;
|
|
|
|
private:
|
|
class VulkanSurfaceProducer
|
|
: public flow::SceneUpdateContext::SurfaceProducer,
|
|
private mtl::MessageLoopHandler {
|
|
public:
|
|
VulkanSurfaceProducer();
|
|
sk_sp<SkSurface> ProduceSurface(SkISize size,
|
|
mozart::ImagePtr* out_image) override;
|
|
|
|
void Tick();
|
|
bool FinishFrame();
|
|
bool IsValid() const { return valid_; }
|
|
|
|
private:
|
|
// |mtl::MessageLoopHandler|
|
|
void OnHandleReady(mx_handle_t handle, mx_signals_t pending) override;
|
|
|
|
struct Surface {
|
|
sk_sp<GrVkBackendContext> backend_context;
|
|
sk_sp<SkSurface> sk_surface;
|
|
mx::vmo vmo;
|
|
mx::eventpair local_retention_event;
|
|
mx::eventpair remote_retention_event;
|
|
VkImage vk_image;
|
|
VkDeviceMemory vk_memory;
|
|
|
|
Surface(sk_sp<GrVkBackendContext> backend_context,
|
|
sk_sp<SkSurface> sk_surface,
|
|
mx::vmo vmo,
|
|
mx::eventpair local_retention_event,
|
|
mx::eventpair remote_retention_event,
|
|
VkImage vk_image,
|
|
VkDeviceMemory vk_memory)
|
|
: backend_context(std::move(backend_context)),
|
|
sk_surface(std::move(sk_surface)),
|
|
vmo(std::move(vmo)),
|
|
local_retention_event(std::move(local_retention_event)),
|
|
remote_retention_event(std::move(remote_retention_event)),
|
|
vk_image(vk_image),
|
|
vk_memory(vk_memory) {}
|
|
|
|
~Surface() {
|
|
FTL_DCHECK(backend_context);
|
|
vkFreeMemory(backend_context->fDevice, vk_memory, NULL);
|
|
vkDestroyImage(backend_context->fDevice, vk_image, NULL);
|
|
}
|
|
};
|
|
|
|
std::unique_ptr<Surface> CreateSurface(uint32_t width, uint32_t height);
|
|
|
|
struct Swapchain {
|
|
std::queue<std::unique_ptr<Surface>> queue;
|
|
uint32_t tick_count = 0;
|
|
static constexpr uint32_t kMaxSurfaces = 3;
|
|
static constexpr uint32_t kMaxTickBeforeDiscard = 3;
|
|
};
|
|
|
|
using size_key_t = uint64_t;
|
|
static size_key_t MakeSizeKey(uint32_t width, uint32_t height) {
|
|
return (static_cast<uint64_t>(width) << 32) |
|
|
static_cast<uint64_t>(height);
|
|
}
|
|
|
|
ftl::RefPtr<vulkan::VulkanProcTable> vk_;
|
|
std::unique_ptr<vulkan::VulkanApplication> application_;
|
|
std::unique_ptr<vulkan::VulkanDevice> logical_device_;
|
|
sk_sp<GrVkBackendContext> backend_context_;
|
|
sk_sp<GrContext> context_;
|
|
|
|
// These three containers hold surfaces in various stages of recycling
|
|
|
|
// Buffers exist in available_surfaces_ when they are ready to be recycled
|
|
// ProduceSurface will look here for an appropriately sized surface before
|
|
// creating a new one
|
|
// The Swapchain's tick_count is incremented in Tick and decremented when
|
|
// a surface is taken from the queue, when the tick count goes above
|
|
// kMaxTickBeforeDiscard the Swapchain is discarded. Newly surfaces are
|
|
// added to the queue iff there aar less than kMaxSurfaces already in the
|
|
// queue
|
|
std::unordered_map<size_key_t, Swapchain> available_surfaces_;
|
|
|
|
struct PendingSurfaceInfo {
|
|
mtl::MessageLoop::HandlerKey handler_key;
|
|
std::unique_ptr<Surface> surface;
|
|
mx::eventpair production_fence;
|
|
};
|
|
// Surfaces produced by ProduceSurface live in outstanding_surfaces_ until
|
|
// FinishFrame is called, at which point they are moved to pending_surfaces_
|
|
std::vector<PendingSurfaceInfo> outstanding_surfaces_;
|
|
// Surfaces exist in pendind surfaces until they are released by the buffer
|
|
// consumer
|
|
std::unordered_map<mx_handle_t, PendingSurfaceInfo> pending_surfaces_;
|
|
bool valid_;
|
|
|
|
bool Initialize();
|
|
};
|
|
|
|
flow::CompositorContext compositor_context_;
|
|
mozart::ScenePtr scene_;
|
|
std::unique_ptr<VulkanSurfaceProducer> surface_producer_;
|
|
|
|
bool Draw(std::unique_ptr<flow::LayerTree> layer_tree);
|
|
|
|
FTL_DISALLOW_COPY_AND_ASSIGN(VulkanRasterizer);
|
|
};
|
|
|
|
} // namespace flutter_runner
|
|
|
|
#endif // FLUTTER_CONTENT_HANDLER_VULKAN_RASTERIZER_H_
|