1 | // Copyright 2013 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #include "flutter/shell/gpu/gpu_surface_vulkan_impeller.h" |
6 | |
7 | #include "flutter/fml/make_copyable.h" |
8 | #include "flutter/impeller/display_list/dl_dispatcher.h" |
9 | #include "flutter/impeller/renderer/renderer.h" |
10 | #include "impeller/renderer/backend/vulkan/surface_context_vk.h" |
11 | #include "impeller/renderer/surface.h" |
12 | |
13 | namespace flutter { |
14 | |
15 | GPUSurfaceVulkanImpeller::GPUSurfaceVulkanImpeller( |
16 | std::shared_ptr<impeller::Context> context) { |
17 | if (!context || !context->IsValid()) { |
18 | return; |
19 | } |
20 | |
21 | auto renderer = std::make_shared<impeller::Renderer>(args&: context); |
22 | if (!renderer->IsValid()) { |
23 | return; |
24 | } |
25 | |
26 | auto aiks_context = std::make_shared<impeller::AiksContext>(args&: context); |
27 | if (!aiks_context->IsValid()) { |
28 | return; |
29 | } |
30 | |
31 | impeller_context_ = std::move(context); |
32 | impeller_renderer_ = std::move(renderer); |
33 | aiks_context_ = std::move(aiks_context); |
34 | is_valid_ = true; |
35 | } |
36 | |
37 | // |Surface| |
38 | GPUSurfaceVulkanImpeller::~GPUSurfaceVulkanImpeller() = default; |
39 | |
40 | // |Surface| |
41 | bool GPUSurfaceVulkanImpeller::IsValid() { |
42 | return is_valid_; |
43 | } |
44 | |
45 | // |Surface| |
46 | std::unique_ptr<SurfaceFrame> GPUSurfaceVulkanImpeller::AcquireFrame( |
47 | const SkISize& size) { |
48 | if (!IsValid()) { |
49 | FML_LOG(ERROR) << "Vulkan surface was invalid." ; |
50 | return nullptr; |
51 | } |
52 | |
53 | if (size.isEmpty()) { |
54 | FML_LOG(ERROR) << "Vulkan surface was asked for an empty frame." ; |
55 | return nullptr; |
56 | } |
57 | |
58 | auto& context_vk = impeller::SurfaceContextVK::Cast(base&: *impeller_context_); |
59 | std::unique_ptr<impeller::Surface> surface = context_vk.AcquireNextSurface(); |
60 | |
61 | SurfaceFrame::SubmitCallback submit_callback = |
62 | fml::MakeCopyable(lambda: [renderer = impeller_renderer_, // |
63 | aiks_context = aiks_context_, // |
64 | surface = std::move(surface) // |
65 | ](SurfaceFrame& surface_frame, DlCanvas* canvas) mutable -> bool { |
66 | if (!aiks_context) { |
67 | return false; |
68 | } |
69 | |
70 | auto display_list = surface_frame.BuildDisplayList(); |
71 | if (!display_list) { |
72 | FML_LOG(ERROR) << "Could not build display list for surface frame." ; |
73 | return false; |
74 | } |
75 | |
76 | auto cull_rect = |
77 | surface->GetTargetRenderPassDescriptor().GetRenderTargetSize(); |
78 | impeller::Rect dl_cull_rect = impeller::Rect::MakeSize(size: cull_rect); |
79 | impeller::DlDispatcher impeller_dispatcher(dl_cull_rect); |
80 | display_list->Dispatch( |
81 | ctx&: impeller_dispatcher, |
82 | cull_rect: SkIRect::MakeWH(w: cull_rect.width, h: cull_rect.height)); |
83 | auto picture = impeller_dispatcher.EndRecordingAsPicture(); |
84 | |
85 | return renderer->Render( |
86 | surface: std::move(surface), |
87 | callback: fml::MakeCopyable( |
88 | lambda: [aiks_context, picture = std::move(picture)]( |
89 | impeller::RenderTarget& render_target) -> bool { |
90 | return aiks_context->Render(picture, render_target); |
91 | })); |
92 | }); |
93 | |
94 | return std::make_unique<SurfaceFrame>( |
95 | args: nullptr, // surface |
96 | args: SurfaceFrame::FramebufferInfo{}, // framebuffer info |
97 | args&: submit_callback, // submit callback |
98 | args: size, // frame size |
99 | args: nullptr, // context result |
100 | args: true // display list fallback |
101 | ); |
102 | } |
103 | |
104 | // |Surface| |
105 | SkMatrix GPUSurfaceVulkanImpeller::GetRootTransformation() const { |
106 | // This backend does not currently support root surface transformations. Just |
107 | // return identity. |
108 | return {}; |
109 | } |
110 | |
111 | // |Surface| |
112 | GrDirectContext* GPUSurfaceVulkanImpeller::GetContext() { |
113 | // Impeller != Skia. |
114 | return nullptr; |
115 | } |
116 | |
117 | // |Surface| |
118 | std::unique_ptr<GLContextResult> |
119 | GPUSurfaceVulkanImpeller::MakeRenderContextCurrent() { |
120 | // This backend has no such concept. |
121 | return std::make_unique<GLContextDefaultResult>(args: true); |
122 | } |
123 | |
124 | // |Surface| |
125 | bool GPUSurfaceVulkanImpeller::EnableRasterCache() const { |
126 | return false; |
127 | } |
128 | |
129 | // |Surface| |
130 | std::shared_ptr<impeller::AiksContext> |
131 | GPUSurfaceVulkanImpeller::GetAiksContext() const { |
132 | return aiks_context_; |
133 | } |
134 | |
135 | } // namespace flutter |
136 | |