10#import <Metal/Metal.h>
11#import <QuartzCore/QuartzCore.h>
20#include "third_party/skia/include/core/SkColorSpace.h"
21#include "third_party/skia/include/core/SkColorType.h"
22#include "third_party/skia/include/core/SkRefCnt.h"
23#include "third_party/skia/include/core/SkSurface.h"
24#include "third_party/skia/include/core/SkSurfaceProps.h"
25#include "third_party/skia/include/gpu/GpuTypes.h"
26#include "third_party/skia/include/gpu/ganesh/GrBackendSurface.h"
27#include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h"
28#include "third_party/skia/include/gpu/ganesh/mtl/GrMtlBackendSurface.h"
29#include "third_party/skia/include/gpu/ganesh/mtl/GrMtlTypes.h"
30#include "third_party/skia/include/ports/SkCFObject.h"
32static_assert(__has_feature(objc_arc),
"ARC must be enabled.");
37sk_sp<SkSurface> CreateSurfaceFromMetalTexture(GrDirectContext* context,
39 GrSurfaceOrigin origin,
41 sk_sp<SkColorSpace> color_space,
42 const SkSurfaceProps* props,
43 SkSurfaces::TextureReleaseProc release_proc,
44 SkSurface::ReleaseContext release_context) {
45 GrMtlTextureInfo info;
46 info.fTexture.retain((__bridge GrMTLHandle)
texture);
47 GrBackendTexture backend_texture =
48 GrBackendTextures::MakeMtl(
texture.width,
texture.height, skgpu::Mipmapped::kNo, info);
49 return SkSurfaces::WrapBackendTexture(context, backend_texture, origin, 1,
color_type,
50 std::move(color_space), props, release_proc,
56 sk_sp<GrDirectContext> context,
57 bool render_to_surface)
59 render_target_type_(delegate->GetRenderTargetType()),
60 context_(
std::move(context)),
61 render_to_surface_(render_to_surface) {
63 NSNumber* disablePartialRepaint =
64 [[NSBundle mainBundle] objectForInfoDictionaryKey:
@"FLTDisablePartialRepaint"];
65 if (disablePartialRepaint != nil) {
66 disable_partial_repaint_ = disablePartialRepaint.boolValue;
74 return context_ !=
nullptr;
77void GPUSurfaceMetalSkia::PrecompileKnownSkSLsIfNecessary() {
78 auto* current_context = GetContext();
79 if (current_context == precompiled_sksl_context_) {
83 precompiled_sksl_context_ = current_context;
88std::unique_ptr<SurfaceFrame> GPUSurfaceMetalSkia::AcquireFrame(
const DlISize& frame_size) {
90 FML_LOG(ERROR) <<
"Metal surface was invalid.";
94 if (frame_size.IsEmpty()) {
95 FML_LOG(ERROR) <<
"Metal surface was asked for an empty frame.";
99 if (!render_to_surface_) {
100 return std::make_unique<SurfaceFrame>(
102 SurfaceFrame::FramebufferInfo(),
103 [](
const SurfaceFrame& surface_frame, DlCanvas* canvas) {
return true; },
104 [](
const SurfaceFrame& surface_frame) {
return true; },
109 PrecompileKnownSkSLsIfNecessary();
111 switch (render_target_type_) {
113 return AcquireFrameFromCAMetalLayer(frame_size);
115 return AcquireFrameFromMTLTexture(frame_size);
117 FML_CHECK(
false) <<
"Unknown MTLRenderTargetType type.";
123std::unique_ptr<SurfaceFrame> GPUSurfaceMetalSkia::AcquireFrameFromCAMetalLayer(
125 CAMetalLayer* layer = (__bridge CAMetalLayer*)delegate_->
GetCAMetalLayer(frame_info);
127 FML_LOG(ERROR) <<
"Invalid CAMetalLayer given by the embedder.";
132 id<CAMetalDrawable> drawable = [layer nextDrawable];
134 FML_LOG(ERROR) <<
"Could not obtain drawable from the metal layer.";
138 auto surface = CreateSurfaceFromMetalTexture(context_.get(), drawable.texture,
139 kTopLeft_GrSurfaceOrigin,
140 kBGRA_8888_SkColorType,
148 FML_LOG(ERROR) <<
"Could not create the SkSurface from the CAMetalLayer.";
154 [
this, drawable, layer](
const SurfaceFrame& surface_frame,
DlCanvas* canvas) ->
bool {
155 layer.presentsWithTransaction = surface_frame.submit_info().present_with_transaction;
156 if (canvas ==
nullptr) {
157 FML_DLOG(ERROR) <<
"Canvas not available.";
166 if (!disable_partial_repaint_) {
167 void*
texture = (__bridge
void*)drawable.texture;
168 for (
auto& entry : damage_) {
171 if (surface_frame.submit_info().frame_damage) {
172 entry.second = entry.second.Union(*surface_frame.submit_info().frame_damage);
185 [
this, drawable](
const SurfaceFrame& surface_frame) ->
bool {
190 SurfaceFrame::FramebufferInfo framebuffer_info;
191 framebuffer_info.supports_readback =
true;
193 if (!disable_partial_repaint_) {
196 void*
texture = (__bridge
void*)drawable.texture;
198 if (
i != damage_.end()) {
199 framebuffer_info.existing_damage =
i->second;
201 framebuffer_info.supports_partial_repaint =
true;
204 return std::make_unique<SurfaceFrame>(std::move(surface), framebuffer_info, encode_callback,
205 submit_callback, frame_info);
208std::unique_ptr<SurfaceFrame> GPUSurfaceMetalSkia::AcquireFrameFromMTLTexture(
211 id<MTLTexture> mtl_texture = (__bridge id<MTLTexture>)
texture.
texture;
214 FML_LOG(ERROR) <<
"Invalid MTLTexture given by the embedder.";
218 sk_sp<SkSurface>
surface = CreateSurfaceFromMetalTexture(
219 context_.get(), mtl_texture, kTopLeft_GrSurfaceOrigin, kBGRA_8888_SkColorType,
nullptr,
220 nullptr,
static_cast<SkSurfaces::TextureReleaseProc
>(
texture.destruction_callback),
224 FML_LOG(ERROR) <<
"Could not create the SkSurface from the metal texture.";
228 auto encode_callback = [](
const SurfaceFrame& surface_frame,
DlCanvas* canvas) ->
bool {
229 if (canvas ==
nullptr) {
230 FML_DLOG(ERROR) <<
"Canvas not available.";
242 delegate = delegate_](
const SurfaceFrame& surface_frame) {
243 TRACE_EVENT0(
"flutter",
"GPUSurfaceMetal::PresentTexture");
244 return delegate->PresentTexture(
texture);
247 SurfaceFrame::FramebufferInfo framebuffer_info;
248 framebuffer_info.supports_readback =
true;
250 return std::make_unique<SurfaceFrame>(std::move(surface), framebuffer_info, encode_callback,
251 submit_callback, frame_info);
255DlMatrix GPUSurfaceMetalSkia::GetRootTransformation()
const {
262GrDirectContext* GPUSurfaceMetalSkia::GetContext() {
263 return context_.get();
267std::unique_ptr<GLContextResult> GPUSurfaceMetalSkia::MakeRenderContextCurrent() {
270 PrecompileKnownSkSLsIfNecessary();
273 return std::make_unique<GLContextDefaultResult>(
true);
276bool GPUSurfaceMetalSkia::AllowsDrawingWhenGpuDisabled()
const {
static PersistentCache * GetCacheForProcess()
size_t PrecompileKnownSkSLs(GrDirectContext *context) const
Precompile SkSLs packaged with the application and gathered during previous runs in the given context...
std::function< bool(SurfaceFrame &surface_frame, DlCanvas *canvas)> EncodeCallback
std::function< bool(SurfaceFrame &surface_frame)> SubmitCallback
#define FML_DLOG(severity)
#define FML_LOG(severity)
#define FML_CHECK(condition)
impeller::Matrix DlMatrix
impeller::ISize32 DlISize
impeller::IRect32 DlIRect
flutter::DlCanvas DlCanvas
GPUMTLTextureHandle texture
#define TRACE_EVENT0(category_group, name)