Skip to content

Commit db3c4a1

Browse files
chinmaygardednfield
authored andcommitted
Make the Metal drawable wrapping routine from the playground a utility.
1 parent 57a0728 commit db3c4a1

File tree

8 files changed

+183
-81
lines changed

8 files changed

+183
-81
lines changed

impeller/playground/playground.mm

Lines changed: 4 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
#include "impeller/playground/playground.h"
1212
#include "impeller/renderer/allocator.h"
1313
#include "impeller/renderer/backend/metal/context_mtl.h"
14+
#include "impeller/renderer/backend/metal/surface_mtl.h"
1415
#include "impeller/renderer/backend/metal/texture_mtl.h"
1516
#include "impeller/renderer/context.h"
1617
#include "impeller/renderer/formats.h"
1718
#include "impeller/renderer/render_pass.h"
1819
#include "impeller/renderer/renderer.h"
19-
#include "impeller/renderer/surface.h"
2020

2121
#define GLFW_INCLUDE_NONE
2222
#import "third_party/glfw/include/GLFW/glfw3.h"
@@ -138,81 +138,17 @@ static void PlaygroundKeyCallback(GLFWwindow* window,
138138
return true;
139139
}
140140

141-
auto current_drawable = [layer nextDrawable];
142-
143-
if (!current_drawable) {
144-
VALIDATION_LOG << "Could not acquire current drawable.";
145-
return false;
146-
}
147-
148-
TextureDescriptor msaa_tex_desc;
149-
msaa_tex_desc.type = TextureType::k2DMultisample;
150-
msaa_tex_desc.sample_count = SampleCount::kCount4;
151-
msaa_tex_desc.format = PixelFormat::kB8G8R8A8UNormInt;
152-
msaa_tex_desc.size = {
153-
static_cast<ISize::Type>(current_drawable.texture.width),
154-
static_cast<ISize::Type>(current_drawable.texture.height)};
155-
msaa_tex_desc.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget);
156-
157-
auto msaa_tex =
158-
renderer_.GetContext()->GetPermanentsAllocator()->CreateTexture(
159-
StorageMode::kDeviceTransient, msaa_tex_desc);
160-
if (!msaa_tex) {
161-
FML_LOG(ERROR) << "Could not allocate MSAA resolve texture.";
162-
return false;
163-
}
164-
165-
msaa_tex->SetLabel("PlaygroundMainColor4xMSAA");
166-
167-
TextureDescriptor onscreen_tex_desc;
168-
onscreen_tex_desc.format = PixelFormat::kB8G8R8A8UNormInt;
169-
onscreen_tex_desc.size = msaa_tex_desc.size;
170-
onscreen_tex_desc.usage =
171-
static_cast<uint64_t>(TextureUsage::kRenderTarget);
172-
173-
ColorAttachment color0;
174-
color0.texture = msaa_tex;
175-
color0.clear_color = Color::DarkSlateGray();
176-
color0.load_action = LoadAction::kClear;
177-
color0.store_action = StoreAction::kMultisampleResolve;
178-
color0.resolve_texture = std::make_shared<TextureMTL>(
179-
onscreen_tex_desc, current_drawable.texture);
180-
181-
TextureDescriptor stencil0_tex;
182-
stencil0_tex.type = TextureType::k2DMultisample;
183-
stencil0_tex.sample_count = SampleCount::kCount4;
184-
stencil0_tex.format = PixelFormat::kD32FloatS8UNormInt;
185-
stencil0_tex.size = msaa_tex_desc.size;
186-
stencil0_tex.usage =
187-
static_cast<TextureUsageMask>(TextureUsage::kRenderTarget);
188-
auto stencil_texture =
189-
renderer_.GetContext()->GetPermanentsAllocator()->CreateTexture(
190-
StorageMode::kDeviceTransient, stencil0_tex);
191-
stencil_texture->SetLabel("PlaygroundMainStencil");
192-
193-
StencilAttachment stencil0;
194-
stencil0.texture = stencil_texture;
195-
stencil0.clear_stencil = 0;
196-
stencil0.load_action = LoadAction::kClear;
197-
stencil0.store_action = StoreAction::kDontCare;
198-
199-
RenderTarget desc;
200-
desc.SetColorAttachment(color0, 0u);
201-
desc.SetStencilAttachment(stencil0);
202-
203-
Surface surface(desc);
204-
205141
Renderer::RenderCallback wrapped_callback = [render_callback](auto& pass) {
206142
pass.SetLabel("Playground Main Render Pass");
207143
return render_callback(pass);
208144
};
209145

210-
if (!renderer_.Render(surface, wrapped_callback)) {
146+
if (!renderer_.Render(SurfaceMTL::WrapCurrentMetalLayerDrawable(
147+
renderer_.GetContext(), layer),
148+
wrapped_callback)) {
211149
VALIDATION_LOG << "Could not render into the surface.";
212150
return false;
213151
}
214-
215-
[current_drawable present];
216152
}
217153

218154
return true;

impeller/renderer/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ impeller_component("renderer") {
3131
"backend/metal/shader_function_mtl.mm",
3232
"backend/metal/shader_library_mtl.h",
3333
"backend/metal/shader_library_mtl.mm",
34+
"backend/metal/surface_mtl.h",
35+
"backend/metal/surface_mtl.mm",
3436
"backend/metal/texture_mtl.h",
3537
"backend/metal/texture_mtl.mm",
3638
"backend/metal/vertex_descriptor_mtl.h",
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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+
#pragma once
6+
7+
#include <QuartzCore/CAMetalLayer.h>
8+
9+
#include "flutter/fml/macros.h"
10+
#include "impeller/renderer/context.h"
11+
#include "impeller/renderer/surface.h"
12+
13+
namespace impeller {
14+
15+
class SurfaceMTL final : public Surface {
16+
public:
17+
//----------------------------------------------------------------------------
18+
/// @brief Wraps the current drawable of the given Metal layer to create
19+
/// a surface Impeller can render to. The surface must be created
20+
/// as late as possible and discarded immediately after rendering
21+
/// to it.
22+
///
23+
/// @param[in] context The context
24+
/// @param[in] layer The layer whose current drawable to wrap to create a
25+
/// surface.
26+
///
27+
/// @return A pointer to the wrapped surface or null.
28+
///
29+
static std::unique_ptr<Surface> WrapCurrentMetalLayerDrawable(
30+
std::shared_ptr<Context> context,
31+
CAMetalLayer* layer);
32+
33+
// |Surface|
34+
~SurfaceMTL() override;
35+
36+
// |Surface|
37+
bool Present() const override;
38+
39+
private:
40+
id<MTLDrawable> drawable_ = nil;
41+
42+
SurfaceMTL(RenderTarget target, id<MTLDrawable> drawable);
43+
44+
FML_DISALLOW_COPY_AND_ASSIGN(SurfaceMTL);
45+
};
46+
47+
} // namespace impeller
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
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 "impeller/renderer/backend/metal/surface_mtl.h"
6+
7+
#include "flutter/fml/trace_event.h"
8+
#include "impeller/base/validation.h"
9+
#include "impeller/renderer/backend/metal/texture_mtl.h"
10+
#include "impeller/renderer/render_target.h"
11+
12+
namespace impeller {
13+
14+
std::unique_ptr<Surface> SurfaceMTL::WrapCurrentMetalLayerDrawable(
15+
std::shared_ptr<Context> context,
16+
CAMetalLayer* layer) {
17+
TRACE_EVENT0("flutter", __FUNCTION__);
18+
19+
if (context == nullptr || !context->IsValid() || layer == nil) {
20+
return nullptr;
21+
}
22+
23+
auto current_drawable = [layer nextDrawable];
24+
25+
if (!current_drawable) {
26+
VALIDATION_LOG << "Could not acquire current drawable.";
27+
return nullptr;
28+
}
29+
30+
TextureDescriptor msaa_tex_desc;
31+
msaa_tex_desc.type = TextureType::k2DMultisample;
32+
msaa_tex_desc.sample_count = SampleCount::kCount4;
33+
msaa_tex_desc.format = PixelFormat::kB8G8R8A8UNormInt;
34+
msaa_tex_desc.size = {
35+
static_cast<ISize::Type>(current_drawable.texture.width),
36+
static_cast<ISize::Type>(current_drawable.texture.height)};
37+
msaa_tex_desc.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget);
38+
39+
auto msaa_tex = context->GetPermanentsAllocator()->CreateTexture(
40+
StorageMode::kDeviceTransient, msaa_tex_desc);
41+
if (!msaa_tex) {
42+
FML_LOG(ERROR) << "Could not allocate MSAA resolve texture.";
43+
return nullptr;
44+
}
45+
46+
msaa_tex->SetLabel("PlaygroundMainColor4xMSAA");
47+
48+
TextureDescriptor onscreen_tex_desc;
49+
onscreen_tex_desc.format = PixelFormat::kB8G8R8A8UNormInt;
50+
onscreen_tex_desc.size = msaa_tex_desc.size;
51+
onscreen_tex_desc.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget);
52+
53+
ColorAttachment color0;
54+
color0.texture = msaa_tex;
55+
color0.clear_color = Color::DarkSlateGray();
56+
color0.load_action = LoadAction::kClear;
57+
color0.store_action = StoreAction::kMultisampleResolve;
58+
color0.resolve_texture =
59+
std::make_shared<TextureMTL>(onscreen_tex_desc, current_drawable.texture);
60+
61+
TextureDescriptor stencil0_tex;
62+
stencil0_tex.type = TextureType::k2DMultisample;
63+
stencil0_tex.sample_count = SampleCount::kCount4;
64+
stencil0_tex.format = PixelFormat::kD32FloatS8UNormInt;
65+
stencil0_tex.size = msaa_tex_desc.size;
66+
stencil0_tex.usage =
67+
static_cast<TextureUsageMask>(TextureUsage::kRenderTarget);
68+
auto stencil_texture = context->GetPermanentsAllocator()->CreateTexture(
69+
StorageMode::kDeviceTransient, stencil0_tex);
70+
stencil_texture->SetLabel("PlaygroundMainStencil");
71+
72+
StencilAttachment stencil0;
73+
stencil0.texture = stencil_texture;
74+
stencil0.clear_stencil = 0;
75+
stencil0.load_action = LoadAction::kClear;
76+
stencil0.store_action = StoreAction::kDontCare;
77+
78+
RenderTarget desc;
79+
desc.SetColorAttachment(color0, 0u);
80+
desc.SetStencilAttachment(stencil0);
81+
82+
// The constructor is private. So make_unique may not be used.
83+
return std::unique_ptr<SurfaceMTL>(
84+
new SurfaceMTL(std::move(desc), current_drawable));
85+
}
86+
87+
SurfaceMTL::SurfaceMTL(RenderTarget target, id<MTLDrawable> drawable)
88+
: Surface(std::move(target)), drawable_(drawable) {}
89+
90+
// |Surface|
91+
SurfaceMTL::~SurfaceMTL() = default;
92+
93+
// |Surface|
94+
bool SurfaceMTL::Present() const {
95+
if (drawable_ == nil) {
96+
return false;
97+
}
98+
99+
[drawable_ present];
100+
return true;
101+
}
102+
103+
} // namespace impeller

impeller/renderer/renderer.cc

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ bool Renderer::IsValid() const {
3131
return is_valid_;
3232
}
3333

34-
bool Renderer::Render(const Surface& surface,
34+
bool Renderer::Render(std::unique_ptr<Surface> surface,
3535
RenderCallback render_callback) const {
3636
if (!IsValid()) {
3737
return false;
3838
}
3939

40-
if (!surface.IsValid()) {
40+
if (!surface || !surface->IsValid()) {
4141
return false;
4242
}
4343

@@ -49,8 +49,8 @@ bool Renderer::Render(const Surface& surface,
4949

5050
command_buffer->SetLabel("Onscreen Command Buffer");
5151

52-
auto render_pass =
53-
command_buffer->CreateRenderPass(surface.GetTargetRenderPassDescriptor());
52+
auto render_pass = command_buffer->CreateRenderPass(
53+
surface->GetTargetRenderPassDescriptor());
5454
if (!render_pass) {
5555
return false;
5656
}
@@ -67,13 +67,17 @@ bool Renderer::Render(const Surface& surface,
6767
return false;
6868
}
6969

70-
return command_buffer->SubmitCommands(
71-
[sema = frames_in_flight_sema_](CommandBuffer::Status result) {
72-
sema->Signal();
73-
if (result != CommandBuffer::Status::kCompleted) {
74-
VALIDATION_LOG << "Could not commit command buffer.";
75-
}
76-
});
70+
if (!command_buffer->SubmitCommands(
71+
[sema = frames_in_flight_sema_](CommandBuffer::Status result) {
72+
sema->Signal();
73+
if (result != CommandBuffer::Status::kCompleted) {
74+
VALIDATION_LOG << "Could not commit command buffer.";
75+
}
76+
})) {
77+
return false;
78+
}
79+
80+
return surface->Present();
7781
}
7882

7983
std::shared_ptr<Context> Renderer::GetContext() const {

impeller/renderer/renderer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class Renderer {
3232

3333
bool IsValid() const;
3434

35-
bool Render(const Surface& surface, RenderCallback callback) const;
35+
bool Render(std::unique_ptr<Surface> surface, RenderCallback callback) const;
3636

3737
std::shared_ptr<Context> GetContext() const;
3838

impeller/renderer/surface.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
namespace impeller {
1010

11+
Surface::Surface() : Surface(RenderTarget{}) {}
12+
1113
Surface::Surface(RenderTarget target_desc) : desc_(std::move(target_desc)) {
1214
if (auto size = desc_.GetColorAttachmentSize(0u); size.has_value()) {
1315
size_ = size.value();
@@ -32,4 +34,8 @@ const RenderTarget& Surface::GetTargetRenderPassDescriptor() const {
3234
return desc_;
3335
}
3436

37+
bool Surface::Present() const {
38+
return false;
39+
};
40+
3541
} // namespace impeller

impeller/renderer/surface.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,20 @@ namespace impeller {
1616

1717
class Surface {
1818
public:
19+
Surface();
20+
1921
Surface(RenderTarget target_desc);
2022

21-
~Surface();
23+
virtual ~Surface();
2224

2325
const ISize& GetSize() const;
2426

2527
bool IsValid() const;
2628

2729
const RenderTarget& GetTargetRenderPassDescriptor() const;
2830

31+
virtual bool Present() const;
32+
2933
private:
3034
RenderTarget desc_;
3135
ISize size_;

0 commit comments

Comments
 (0)