blob: abe27c01deeff651366565263d7839a0bcfb343c [file] [log] [blame]
// 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_