|
5 | 5 | #include "flutter/shell/gpu/gpu_surface_metal.h" |
6 | 6 |
|
7 | 7 | #import <Metal/Metal.h> |
8 | | -#include "include/core/SkSize.h" |
9 | 8 |
|
10 | 9 | #include "flutter/fml/make_copyable.h" |
11 | 10 | #include "flutter/fml/platform/darwin/cf_utils.h" |
|
24 | 23 | render_target_type_(delegate->GetRenderTargetType()), |
25 | 24 | context_(std::move(context)) {} |
26 | 25 |
|
27 | | -GPUSurfaceMetal::~GPUSurfaceMetal() = default; |
| 26 | +GPUSurfaceMetal::~GPUSurfaceMetal() { |
| 27 | + ReleaseUnusedDrawableIfNecessary(); |
| 28 | +} |
28 | 29 |
|
29 | 30 | // |Surface| |
30 | 31 | bool GPUSurfaceMetal::IsValid() { |
|
63 | 64 | return nullptr; |
64 | 65 | } |
65 | 66 |
|
66 | | - GrMTLHandle drawable_raw; |
| 67 | + ReleaseUnusedDrawableIfNecessary(); |
67 | 68 | sk_sp<SkSurface> surface = |
68 | 69 | SkSurface::MakeFromCAMetalLayer(context_.get(), // context |
69 | 70 | layer, // layer |
|
72 | 73 | kBGRA_8888_SkColorType, // color type |
73 | 74 | nullptr, // colorspace |
74 | 75 | nullptr, // surface properties |
75 | | - &drawable_raw // drawable (transfer out) |
| 76 | + &next_drawable_ // drawable (transfer out) |
76 | 77 | ); |
77 | | - fml::CFRef<GrMTLHandle> drawable(drawable_raw); |
78 | 78 |
|
79 | 79 | if (!surface) { |
80 | 80 | FML_LOG(ERROR) << "Could not create the SkSurface from the CAMetalLayer."; |
81 | 81 | return nullptr; |
82 | 82 | } |
83 | 83 |
|
84 | 84 | auto submit_callback = |
85 | | - fml::MakeCopyable([drawable = std::move(drawable), delegate = delegate_]( |
| 85 | + fml::MakeCopyable([drawable = next_drawable_, delegate = delegate_]( |
86 | 86 | const SurfaceFrame& surface_frame, SkCanvas* canvas) -> bool { |
87 | 87 | TRACE_EVENT0("flutter", "GPUSurfaceMetal::Submit"); |
88 | 88 | if (canvas == nullptr) { |
|
92 | 92 |
|
93 | 93 | canvas->flush(); |
94 | 94 |
|
| 95 | + if (!drawable) { |
| 96 | + FML_DLOG(ERROR) << "Unable to obtain a metal drawable."; |
| 97 | + return false; |
| 98 | + } |
| 99 | + |
95 | 100 | return delegate->PresentDrawable(drawable); |
96 | 101 | }); |
97 | 102 |
|
|
155 | 160 | return std::make_unique<GLContextDefaultResult>(true); |
156 | 161 | } |
157 | 162 |
|
| 163 | +void GPUSurfaceMetal::ReleaseUnusedDrawableIfNecessary() { |
| 164 | + // If the previous surface frame was not submitted before a new one is acquired, the old drawable |
| 165 | + // needs to be released. An RAII wrapper may not be used because this needs to interoperate with |
| 166 | + // Skia APIs. |
| 167 | + if (next_drawable_ == nullptr) { |
| 168 | + return; |
| 169 | + } |
| 170 | + |
| 171 | + CFRelease(next_drawable_); |
| 172 | + next_drawable_ = nullptr; |
| 173 | +} |
| 174 | + |
158 | 175 | } // namespace flutter |
0 commit comments