提交 2a4af690 编写于 作者: F freiling 提交者: Chinmay Garde

Back Vulkan Rasterizer with Mozart View (#3568)

This version does not recycle buffers. It is meant only as an initial solution,
and the proper buffer recycling logic has been broken out into a separate change
上级 9bc769a7
......@@ -6,6 +6,7 @@ assert(is_fuchsia)
declare_args() {
flutter_enable_vulkan = false
flutter_use_vulkan_native_surface = false
}
executable("content_handler") {
......@@ -66,16 +67,23 @@ executable("content_handler") {
]
if (flutter_enable_vulkan) {
defines += [ "FLUTTER_ENABLE_VULKAN" ]
defines += [ "FLUTTER_ENABLE_VULKAN=1" ]
libs += [ "hid" ]
sources += [
"direct_input.cc",
"direct_input.h",
"vulkan_rasterizer.cc",
"vulkan_rasterizer.h",
]
if (flutter_use_vulkan_native_surface) {
defines += [ "FLUTTER_USE_VULKAN_NATIVE_SURFACE=1" ]
sources += [
"direct_input.cc",
"direct_input.h",
"vulkan_native_rasterizer.cc",
"vulkan_native_rasterizer.h",
]
libs += [ "hid" ]
} else {
sources += [
"vulkan_rasterizer.cc",
"vulkan_rasterizer.h",
]
}
deps += [
"//flutter/vulkan",
......
......@@ -7,7 +7,11 @@
#include "flutter/content_handler/software_rasterizer.h"
#if FLUTTER_ENABLE_VULKAN
#if FLUTTER_USE_VULKAN_NATIVE_SURFACE
#include "flutter/content_handler/vulkan_native_rasterizer.h"
#else // FLUTTER_USE_VULKAN_NATIVE_SURFACE
#include "flutter/content_handler/vulkan_rasterizer.h"
#endif // FLUTTER_USE_VULKAN_NATIVE_SURFACE
#endif // FLUTTER_ENABLE_VULKAN
namespace flutter_runner {
......@@ -16,7 +20,11 @@ Rasterizer::~Rasterizer() = default;
std::unique_ptr<Rasterizer> Rasterizer::Create() {
#if FLUTTER_ENABLE_VULKAN
#if FLUTTER_USE_VULKAN_NATIVE_SURFACE
auto vulkan_rasterizer = std::make_unique<VulkanNativeRasterizer>();
#else // FLUTTER_USE_VULKAN_NATIVE_SURFACE
auto vulkan_rasterizer = std::make_unique<VulkanRasterizer>();
#endif // FLUTTER_USE_VULKAN_NATIVE_SURFACE
if (!vulkan_rasterizer->IsValid()) {
FTL_DLOG(INFO) << "Could not initialize a valid vulkan rasterizer. "
......
......@@ -140,14 +140,14 @@ void RuntimeHolder::CreateView(
input_listener_binding_.Bind(GetProxy(&input_listener));
input_connection_->SetEventListener(std::move(input_listener));
#if FLUTTER_ENABLE_VULKAN
#if FLUTTER_ENABLE_VULKAN && FLUTTER_USE_VULKAN_NATIVE_SURFACE
direct_input_ = std::make_unique<DirectInput>(
[this](const blink::PointerDataPacket& packet) -> void {
runtime_->DispatchPointerDataPacket(packet);
});
FTL_DCHECK(direct_input_->IsValid());
direct_input_->WaitForReadAvailability();
#endif // FLUTTER_ENABLE_VULKAN
#endif // FLUTTER_ENABLE_VULKAN && FLUTTER_USE_VULKAN_NATIVE_SURFACE
mozart::ScenePtr scene;
view_->CreateScene(fidl::GetProxy(&scene));
......@@ -158,9 +158,9 @@ void RuntimeHolder::CreateView(
runtime_ = blink::RuntimeController::Create(this);
runtime_->CreateDartController(script_uri);
runtime_->SetViewportMetrics(viewport_metrics_);
#if FLUTTER_ENABLE_VULKAN
#if FLUTTER_ENABLE_VULKAN && FLUTTER_USE_VULKAN_NATIVE_SURFACE
direct_input_->SetViewportMetrics(viewport_metrics_);
#endif // FLUTTER_ENABLE_VULKAN
#endif // FLUTTER_ENABLE_VULKAN && FLUTTER_USE_VULKAN_NATIVE_SURFACE
if (!kernel.empty()) {
runtime_->dart_controller()->RunFromKernel(kernel.data(), kernel.size());
} else {
......@@ -377,11 +377,11 @@ void RuntimeHolder::OnInvalidation(mozart::ViewInvalidationPtr invalidation,
// TODO(abarth): Use view_properties_->display_metrics->device_pixel_ratio
// once that's reasonable.
runtime_->SetViewportMetrics(viewport_metrics_);
#if FLUTTER_ENABLE_VULKAN
#if FLUTTER_ENABLE_VULKAN && FLUTTER_USE_VULKAN_NATIVE_SURFACE
if (direct_input_) {
direct_input_->SetViewportMetrics(viewport_metrics_);
}
#endif // FLUTTER_ENABLE_VULKAN
#endif // FLUTTER_ENABLE_VULKAN && FLUTTER_USE_VULKAN_NATIVE_SURFACE
}
// Remember the scene version for rendering.
......
......@@ -24,9 +24,9 @@
#include "lib/ftl/macros.h"
#include "lib/ftl/memory/weak_ptr.h"
#if FLUTTER_ENABLE_VULKAN
#if FLUTTER_ENABLE_VULKAN && FLUTTER_USE_VULKAN_NATIVE_SURFACE
#include "flutter/content_handler/direct_input.h"
#endif // FLUTTER_ENABLE_VULKAN
#endif // FLUTTER_ENABLE_VULKAN && FLUTTER_USE_VULKAN_NATIVE_SURFACE
namespace flutter_runner {
class Rasterizer;
......@@ -92,9 +92,9 @@ class RuntimeHolder : public blink::RuntimeDelegate,
mozart::ViewManagerPtr view_manager_;
fidl::Binding<mozart::ViewListener> view_listener_binding_;
fidl::Binding<mozart::InputListener> input_listener_binding_;
#if FLUTTER_ENABLE_VULKAN
#if FLUTTER_ENABLE_VULKAN && FLUTTER_USE_VULKAN_NATIVE_SURFACE
std::unique_ptr<DirectInput> direct_input_;
#endif // FLUTTER_ENABLE_VULKAN
#endif // FLUTTER_ENABLE_VULKAN && FLUTTER_USE_VULKAN_NATIVE_SURFACE
mozart::InputConnectionPtr input_connection_;
mozart::ViewPtr view_;
mozart::ViewPropertiesPtr view_properties_;
......
......@@ -13,13 +13,23 @@
namespace flutter_runner {
SoftwareRasterizer::RasterSurfaceProducer::RasterSurfaceProducer() {
buffer_producer_.reset(new mozart::BufferProducer());
}
sk_sp<SkSurface> SoftwareRasterizer::RasterSurfaceProducer::ProduceSurface(
SkISize size,
mozart::ImagePtr* out_image) {
return mozart::MakeSkSurface(size, buffer_producer_.get(), out_image);
}
SoftwareRasterizer::SoftwareRasterizer() : compositor_context_(nullptr) {}
SoftwareRasterizer::~SoftwareRasterizer() = default;
void SoftwareRasterizer::SetScene(fidl::InterfaceHandle<mozart::Scene> scene) {
scene_.Bind(std::move(scene));
buffer_producer_.reset(new mozart::BufferProducer());
surface_producer_.reset(new RasterSurfaceProducer());
}
void SoftwareRasterizer::Draw(std::unique_ptr<flow::LayerTree> layer_tree,
......@@ -54,7 +64,7 @@ void SoftwareRasterizer::Draw(std::unique_ptr<flow::LayerTree> layer_tree,
layer_tree->Preroll(frame);
flow::SceneUpdateContext context(update.get(), buffer_producer_.get());
flow::SceneUpdateContext context(update.get(), surface_producer_.get());
auto root_node = mozart::Node::New();
root_node->hit_test_behavior = mozart::HitTestBehavior::New();
layer_tree->UpdateScene(context, root_node.get());
......@@ -72,7 +82,7 @@ void SoftwareRasterizer::Draw(std::unique_ptr<flow::LayerTree> layer_tree,
// The image buffer's fence is signalled automatically when the surface
// goes out of scope.
context.ExecutePaintTasks(frame);
buffer_producer_->Tick();
surface_producer_->Tick();
callback();
}
......
......@@ -26,8 +26,20 @@ class SoftwareRasterizer : public Rasterizer {
ftl::Closure callback) override;
private:
class RasterSurfaceProducer
: public flow::SceneUpdateContext::SurfaceProducer {
public:
RasterSurfaceProducer();
sk_sp<SkSurface> ProduceSurface(SkISize size,
mozart::ImagePtr* out_image) override;
void Tick() { buffer_producer_->Tick(); }
private:
std::unique_ptr<mozart::BufferProducer> buffer_producer_;
};
mozart::ScenePtr scene_;
std::unique_ptr<mozart::BufferProducer> buffer_producer_;
std::unique_ptr<RasterSurfaceProducer> surface_producer_;
flow::CompositorContext compositor_context_;
FTL_DISALLOW_COPY_AND_ASSIGN(SoftwareRasterizer);
......
// 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.
#include "flutter/content_handler/vulkan_native_rasterizer.h"
#include <utility>
#include "flutter/vulkan/vulkan_native_surface_magma.h"
namespace flutter_runner {
VulkanNativeRasterizer::VulkanNativeRasterizer()
: compositor_context_(nullptr) {
auto proc_table = ftl::MakeRefCounted<vulkan::VulkanProcTable>();
if (!proc_table->HasAcquiredMandatoryProcAddresses()) {
return;
}
auto native_surface = std::make_unique<vulkan::VulkanNativeSurfaceMagma>();
if (!native_surface->IsValid()) {
return;
}
auto window = std::make_unique<vulkan::VulkanWindow>(
proc_table, std::move(native_surface));
if (!window->IsValid()) {
return;
}
window_ = std::move(window);
}
VulkanNativeRasterizer::~VulkanNativeRasterizer() = default;
bool VulkanNativeRasterizer::IsValid() const {
return window_ == nullptr ? false : window_->IsValid();
}
void VulkanNativeRasterizer::SetScene(
fidl::InterfaceHandle<mozart::Scene> scene) {
// TODO: Composition is currently unsupported using the Vulkan backend.
}
void VulkanNativeRasterizer::Draw(std::unique_ptr<flow::LayerTree> layer_tree,
ftl::Closure callback) {
Draw(std::move(layer_tree));
callback();
}
bool VulkanNativeRasterizer::Draw(std::unique_ptr<flow::LayerTree> layer_tree) {
if (layer_tree == nullptr) {
FTL_DLOG(INFO) << "Layer tree was not valid.";
return false;
}
if (!window_->IsValid()) {
FTL_DLOG(INFO) << "Vulkan window was not valid.";
return false;
}
auto surface = window_->AcquireSurface();
if (!surface && surface->getCanvas() != nullptr) {
FTL_DLOG(INFO) << "Could not acquire a vulkan surface.";
return false;
}
{
auto compositor_frame = compositor_context_.AcquireFrame(
window_->GetSkiaGrContext(), // GrContext*
surface->getCanvas(), // SkCanvas
true // instrumentation
);
layer_tree->Raster(compositor_frame);
}
if (!window_->SwapBuffers()) {
FTL_DLOG(INFO) << "Could not swap buffers successfully.";
return false;
}
return true;
}
} // namespace flutter_runner
// 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 "flutter/content_handler/rasterizer.h"
#include "flutter/flow/compositor_context.h"
#include "flutter/vulkan/vulkan_window.h"
#include "lib/ftl/macros.h"
namespace flutter_runner {
class VulkanNativeRasterizer : public Rasterizer {
public:
VulkanNativeRasterizer();
~VulkanNativeRasterizer() 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:
std::unique_ptr<vulkan::VulkanWindow> window_;
flow::CompositorContext compositor_context_;
bool Draw(std::unique_ptr<flow::LayerTree> layer_tree);
FTL_DISALLOW_COPY_AND_ASSIGN(VulkanNativeRasterizer);
};
} // namespace flutter_runner
#endif // FLUTTER_CONTENT_HANDLER_VULKAN_RASTERIZER_H_
\ No newline at end of file
......@@ -6,41 +6,295 @@
#include <utility>
#include "flutter/vulkan/vulkan_native_surface_magma.h"
#include <unistd.h>
#include "third_party/skia/include/gpu/GrContext.h"
#include "third_party/skia/include/gpu/vk/GrVkTypes.h"
#include "third_party/skia/src/gpu/vk/GrVkUtil.h"
namespace flutter_runner {
VulkanRasterizer::VulkanRasterizer() : compositor_context_(nullptr) {
auto proc_table = ftl::MakeRefCounted<vulkan::VulkanProcTable>();
VulkanRasterizer::VulkanSurfaceProducer::VulkanSurfaceProducer() {
valid_ = Initialize();
if (!valid_)
FTL_DLOG(INFO) << "VulkanSurfaceProducer failed to initialize";
}
if (!proc_table->HasAcquiredMandatoryProcAddresses()) {
return;
sk_sp<SkSurface> VulkanRasterizer::VulkanSurfaceProducer::ProduceSurface(
SkISize size,
mozart::ImagePtr* out_image) {
if (size.isEmpty()) {
FTL_DLOG(INFO) << "Attempting to create surface with empty size";
return nullptr;
}
auto native_surface = std::make_unique<vulkan::VulkanNativeSurfaceMagma>();
// these casts are safe because of the early out on frame_size.isEmpty()
auto width = static_cast<uint32_t>(size.width());
auto height = static_cast<uint32_t>(size.height());
VkResult vk_result;
VkImageCreateInfo image_create_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.pNext = nullptr,
.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
.imageType = VK_IMAGE_TYPE_2D,
.format = VK_FORMAT_B8G8R8A8_UNORM,
.extent = VkExtent3D{width, height, 1},
.mipLevels = 1,
.arrayLayers = 1,
.samples = VK_SAMPLE_COUNT_1_BIT,
.tiling = VK_IMAGE_TILING_OPTIMAL,
.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = nullptr,
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
};
VkImage vk_image;
vk_result = VK_CALL_LOG_ERROR(vkCreateImage(
backend_context_->fDevice, &image_create_info, nullptr, &vk_image));
if (vk_result)
return nullptr;
VkMemoryRequirements memory_reqs;
vkGetImageMemoryRequirements(backend_context_->fDevice, vk_image,
&memory_reqs);
if (!native_surface->IsValid()) {
return;
uint32_t memory_type = 0;
for (; memory_type < 32; memory_type++) {
if ((memory_reqs.memoryTypeBits & (1 << memory_type)))
break;
}
auto window = std::make_unique<vulkan::VulkanWindow>(
proc_table, std::move(native_surface));
VkMemoryAllocateInfo alloc_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.pNext = nullptr,
.allocationSize = memory_reqs.size,
.memoryTypeIndex = memory_type,
};
VkDeviceMemory vk_memory;
vk_result = VK_CALL_LOG_ERROR(vkAllocateMemory(
backend_context_->fDevice, &alloc_info, NULL, &vk_memory));
if (vk_result)
return nullptr;
vk_result = VK_CALL_LOG_ERROR(
vkBindImageMemory(backend_context_->fDevice, vk_image, vk_memory, 0));
if (vk_result)
return nullptr;
const GrVkImageInfo image_info = {
.fImage = vk_image,
.fAlloc = {vk_memory, 0, memory_reqs.size, 0},
.fImageTiling = image_create_info.tiling,
.fImageLayout = image_create_info.initialLayout,
.fFormat = image_create_info.format,
.fLevelCount = image_create_info.mipLevels,
};
GrBackendRenderTargetDesc desc;
desc.fWidth = width;
desc.fHeight = height;
desc.fConfig = kSBGRA_8888_GrPixelConfig;
desc.fOrigin = kTopLeft_GrSurfaceOrigin;
desc.fSampleCnt = 0;
desc.fStencilBits = 0;
desc.fRenderTargetHandle = reinterpret_cast<GrBackendObject>(&image_info);
if (!window->IsValid()) {
return;
SkSurfaceProps props(SkSurfaceProps::InitType::kLegacyFontHost_InitType);
auto sk_surface = SkSurface::MakeFromBackendRenderTarget(
context_.get(), desc, SkColorSpace::MakeSRGB(), &props);
if (!sk_surface) {
FTL_DLOG(INFO) << "MakeFromBackendRenderTarget Failed";
return nullptr;
}
window_ = std::move(window);
uint32_t vmo_handle;
vk_result = VK_CALL_LOG_ERROR(vkExportDeviceMemoryMAGMA(
backend_context_->fDevice, vk_memory, &vmo_handle));
if (vk_result)
return nullptr;
mx::eventpair retention_events[2];
auto mx_status =
mx::eventpair::create(0, &retention_events[0], &retention_events[1]);
if (mx_status) {
FTL_DLOG(INFO) << "Failed to create retention eventpair";
return nullptr;
}
if (!sk_surface || sk_surface->getCanvas() == nullptr) {
FTL_DLOG(INFO) << "surface invalid";
return nullptr;
}
surfaces_.emplace_back(
sk_surface, // sk_sp<SkSurface> sk_surface
mx::vmo(vmo_handle), // mx::vmo vmo
std::move(retention_events[0]), // mx::eventpair local_retention_event;
std::move(retention_events[1]), // mx::eventpair remote_retention_event;
mx::eventpair(), // mx::eventpair fence_event
vk_image, vk_memory);
auto surface = &surfaces_.back();
size_t vmo_size;
surface->vmo.get_size(&vmo_size);
if (vmo_size < memory_reqs.size) {
FTL_DLOG(INFO) << "Failed to allocate sufficiently large vmo";
return nullptr;
}
mx_status_t status;
auto buffer = mozart::Buffer::New();
status = surface->vmo.duplicate(MX_RIGHT_SAME_RIGHTS, &buffer->vmo);
if (status) {
FTL_DLOG(INFO) << "failed to duplicate vmo";
return nullptr;
}
buffer->memory_type = mozart::Buffer::MemoryType::VK_DEVICE_MEMORY;
status = mx::eventpair::create(0, &surface->fence_event, &buffer->fence);
if (status) {
FTL_DLOG(INFO) << "failed to create fence eventpair";
return nullptr;
}
status = surface->remote_retention_event.duplicate(MX_RIGHT_SAME_RIGHTS,
&buffer->retention);
if (status) {
FTL_DLOG(INFO) << "failed to duplicate retention eventpair";
return nullptr;
}
auto image = mozart::Image::New();
image->size = mozart::Size::New();
image->size->width = width;
image->size->height = height;
image->stride = 4 * width;
image->pixel_format = mozart::Image::PixelFormat::B8G8R8A8;
image->alpha_format = mozart::Image::AlphaFormat::OPAQUE;
image->color_space = mozart::Image::ColorSpace::SRGB;
image->buffer = std::move(buffer);
*out_image = std::move(image);
return sk_surface;
}
bool VulkanRasterizer::VulkanSurfaceProducer::Tick() {
mx_status_t status;
for (auto& surface : surfaces_) {
GrVkImageInfo* image_info = nullptr;
if (!surface.sk_surface->getRenderTargetHandle(
reinterpret_cast<GrBackendObject*>(&image_info),
SkSurface::kFlushRead_BackendHandleAccess)) {
FTL_DLOG(INFO) << "Could not get render target handle.";
return false;
}
(void)image_info;
status = surface.fence_event.signal_peer(0u, MX_EPAIR_SIGNALED);
if (status) {
FTL_DLOG(INFO) << "failed to signal fence event";
return false;
}
vkFreeMemory(backend_context_->fDevice, surface.vk_memory, NULL);
vkDestroyImage(backend_context_->fDevice, surface.vk_image, NULL);
}
surfaces_.clear();
return true;
}
bool VulkanRasterizer::VulkanSurfaceProducer::Initialize() {
auto vk = ftl::MakeRefCounted<vulkan::VulkanProcTable>();
std::vector<std::string> extensions = {VK_KHR_SURFACE_EXTENSION_NAME};
application_ = std::make_unique<vulkan::VulkanApplication>(
*vk, "Flutter", std::move(extensions));
if (!application_->IsValid() || !vk->AreInstanceProcsSetup()) {
// Make certain the application instance was created and it setup the
// instance proc table entries.
FTL_DLOG(INFO) << "Instance proc addresses have not been setup.";
return false;
}
// Create the device.
logical_device_ = application_->AcquireFirstCompatibleLogicalDevice();
if (logical_device_ == nullptr || !logical_device_->IsValid() ||
!vk->AreDeviceProcsSetup()) {
// Make certain the device was created and it setup the device proc table
// entries.
FTL_DLOG(INFO) << "Device proc addresses have not been setup.";
return false;
}
if (!vk->HasAcquiredMandatoryProcAddresses()) {
FTL_DLOG(INFO) << "Failed to acquire mandatory proc addresses";
return false;
}
if (!vk->IsValid()) {
FTL_DLOG(INFO) << "VulkanProcTable invalid";
return false;
}
auto interface = vk->CreateSkiaInterface();
if (interface == nullptr || !interface->validate(0)) {
FTL_DLOG(INFO) << "interface invalid";
return false;
}
uint32_t skia_features = 0;
if (!logical_device_->GetPhysicalDeviceFeaturesSkia(&skia_features)) {
FTL_DLOG(INFO) << "Failed to get physical device features";
return false;
}
backend_context_ = sk_make_sp<GrVkBackendContext>();
backend_context_->fInstance = application_->GetInstance();
backend_context_->fPhysicalDevice =
logical_device_->GetPhysicalDeviceHandle();
backend_context_->fDevice = logical_device_->GetHandle();
backend_context_->fQueue = logical_device_->GetQueueHandle();
backend_context_->fGraphicsQueueIndex =
logical_device_->GetGraphicsQueueIndex();
backend_context_->fMinAPIVersion = application_->GetAPIVersion();
backend_context_->fFeatures = skia_features;
backend_context_->fInterface.reset(interface.release());
context_.reset(GrContext::Create(
kVulkan_GrBackend,
reinterpret_cast<GrBackendContext>(backend_context_.get())));
return true;
}
VulkanRasterizer::VulkanRasterizer() : compositor_context_(nullptr) {}
VulkanRasterizer::~VulkanRasterizer() = default;
bool VulkanRasterizer::IsValid() const {
return window_ == nullptr ? false : window_->IsValid();
return !surface_producer_ || surface_producer_->IsValid();
}
void VulkanRasterizer::SetScene(fidl::InterfaceHandle<mozart::Scene> scene) {
// TODO: Composition is currently unsupported using the Vulkan backend.
scene_.Bind(std::move(scene));
surface_producer_.reset(new VulkanSurfaceProducer());
}
void VulkanRasterizer::Draw(std::unique_ptr<flow::LayerTree> layer_tree,
......@@ -55,30 +309,54 @@ bool VulkanRasterizer::Draw(std::unique_ptr<flow::LayerTree> layer_tree) {
return false;
}
if (!window_->IsValid()) {
FTL_DLOG(INFO) << "Vulkan window was not valid.";
if (!scene_) {
FTL_DLOG(INFO) << "Scene was not valid.";
return false;
}
auto surface = window_->AcquireSurface();
const SkISize& frame_size = layer_tree->frame_size();
auto update = mozart::SceneUpdate::New();
// TODO(abarth): Support incremental updates.
update->clear_resources = true;
update->clear_nodes = true;
if (frame_size.isEmpty()) {
update->nodes.insert(mozart::kSceneRootNodeId, mozart::Node::New());
// Publish the updated scene contents.
// TODO(jeffbrown): We should set the metadata's presentation_time here too.
scene_->Update(std::move(update));
auto metadata = mozart::SceneMetadata::New();
metadata->version = layer_tree->scene_version();
scene_->Publish(std::move(metadata));
FTL_DLOG(INFO) << "Publishing empty node";
if (!surface && surface->getCanvas() != nullptr) {
FTL_DLOG(INFO) << "Could not acquire a vulkan surface.";
return false;
}
{
auto compositor_frame = compositor_context_.AcquireFrame(
window_->GetSkiaGrContext(), // GrContext*
surface->getCanvas(), // SkCanvas
true // instrumentation
);
flow::CompositorContext::ScopedFrame frame =
compositor_context_.AcquireFrame(nullptr, nullptr);
layer_tree->Raster(compositor_frame);
}
layer_tree->Preroll(frame);
flow::SceneUpdateContext context(update.get(), surface_producer_.get());
auto root_node = mozart::Node::New();
root_node->hit_test_behavior = mozart::HitTestBehavior::New();
layer_tree->UpdateScene(context, root_node.get());
update->nodes.insert(mozart::kSceneRootNodeId, std::move(root_node));
// Publish the updated scene contents.
// TODO(jeffbrown): We should set the metadata's presentation_time here too.
scene_->Update(std::move(update));
auto metadata = mozart::SceneMetadata::New();
metadata->version = layer_tree->scene_version();
scene_->Publish(std::move(metadata));
if (!window_->SwapBuffers()) {
FTL_DLOG(INFO) << "Could not swap buffers successfully.";
// Draw the contents of the scene to a surface.
// We do this after publishing to take advantage of pipelining.
context.ExecutePaintTasks(frame);
if (!surface_producer_->Tick()) {
FTL_DLOG(INFO) << "Failed to tick surface producer";
return false;
}
......
......@@ -7,10 +7,13 @@
#include <memory>
#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_window.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 {
......@@ -28,9 +31,57 @@ class VulkanRasterizer : public Rasterizer {
ftl::Closure callback) override;
private:
std::unique_ptr<vulkan::VulkanWindow> window_;
class VulkanSurfaceProducer
: public flow::SceneUpdateContext::SurfaceProducer {
public:
VulkanSurfaceProducer();
sk_sp<SkSurface> ProduceSurface(SkISize size,
mozart::ImagePtr* out_image) override;
bool Tick();
bool IsValid() const { return valid_; }
private:
struct Surface {
sk_sp<SkSurface> sk_surface;
mx::vmo vmo;
mx::eventpair local_retention_event;
mx::eventpair remote_retention_event;
mx::eventpair fence_event;
VkImage vk_image;
VkDeviceMemory vk_memory;
Surface(sk_sp<SkSurface> sk_surface,
mx::vmo vmo,
mx::eventpair local_retention_event,
mx::eventpair remote_retention_event,
mx::eventpair fence_event,
VkImage vk_image,
VkDeviceMemory vk_memory)
: 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)),
fence_event(std::move(fence_event)),
vk_image(vk_image),
vk_memory(vk_memory) {}
};
std::vector<Surface> surfaces_;
sk_sp<GrContext> context_;
sk_sp<GrVkBackendContext> backend_context_;
std::unique_ptr<vulkan::VulkanApplication> application_;
std::unique_ptr<vulkan::VulkanDevice> logical_device_;
bool valid_;
bool Initialize();
};
flow::CompositorContext compositor_context_;
mozart::ScenePtr scene_;
bool valid_;
std::unique_ptr<VulkanSurfaceProducer> surface_producer_;
bool CreateOrRecreateSurfaces(uint32_t width, uint32_t height);
bool Draw(std::unique_ptr<flow::LayerTree> layer_tree);
FTL_DISALLOW_COPY_AND_ASSIGN(VulkanRasterizer);
......
......@@ -23,8 +23,8 @@ void SceneUpdateContext::CurrentPaintTask::Clear() {
}
SceneUpdateContext::SceneUpdateContext(mozart::SceneUpdate* update,
mozart::BufferProducer* buffer_producer)
: update_(update), buffer_producer_(buffer_producer) {}
SurfaceProducer* surface_producer)
: update_(update), surface_producer_(surface_producer) {}
SceneUpdateContext::~SceneUpdateContext() = default;
......@@ -60,7 +60,7 @@ mozart::NodePtr SceneUpdateContext::FinalizeCurrentPaintTask(
mozart::ImagePtr image;
PaintTask task;
task.surface = mozart::MakeSkSurface(physical_size, buffer_producer_, &image);
task.surface = surface_producer_->ProduceSurface(physical_size, &image);
task.left = bounds.left();
task.top = bounds.top();
task.scaleX = scaleX;
......
......@@ -35,8 +35,15 @@ class SceneUpdateContext;
class SceneUpdateContext {
public:
class SurfaceProducer {
public:
virtual ~SurfaceProducer() {}
virtual sk_sp<SkSurface> ProduceSurface(SkISize size,
mozart::ImagePtr* out_image) = 0;
};
SceneUpdateContext(mozart::SceneUpdate* update,
mozart::BufferProducer* buffer_producer);
SurfaceProducer* surface_producer);
~SceneUpdateContext();
mozart::SceneUpdate* update() const { return update_; }
......@@ -71,7 +78,7 @@ class SceneUpdateContext {
};
mozart::SceneUpdate* update_;
mozart::BufferProducer* buffer_producer_;
SurfaceProducer* surface_producer_;
CurrentPaintTask current_paint_task_;
std::vector<PaintTask> paint_tasks_;
......
......@@ -1362,6 +1362,8 @@ FILE: ../../../flutter/content_handler/service_protocol_hooks.cc
FILE: ../../../flutter/content_handler/service_protocol_hooks.h
FILE: ../../../flutter/content_handler/software_rasterizer.cc
FILE: ../../../flutter/content_handler/software_rasterizer.h
FILE: ../../../flutter/content_handler/vulkan_native_rasterizer.cc
FILE: ../../../flutter/content_handler/vulkan_native_rasterizer.h
FILE: ../../../flutter/content_handler/vulkan_rasterizer.cc
FILE: ../../../flutter/content_handler/vulkan_rasterizer.h
FILE: ../../../flutter/flow/layers/physical_model_layer.cc
......
......@@ -90,8 +90,12 @@ bool VulkanProcTable::SetupInstanceProcAddresses(
#endif // OS_ANDROID
#if OS_FUCHSIA
ACQUIRE_PROC(CreateMagmaSurfaceKHR, handle);
ACQUIRE_PROC(GetPhysicalDeviceMagmaPresentationSupportKHR, handle);
[this, &handle]() -> bool {
ACQUIRE_PROC(CreateMagmaSurfaceKHR, handle);
ACQUIRE_PROC(GetPhysicalDeviceMagmaPresentationSupportKHR, handle);
return true;
}();
#endif // OS_FUCHSIA
// The debug report functions are optional. We don't want proc acquisition to
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册