7#include "flutter/shell/gpu/gpu_surface_metal_skia.h"
10#import <QuartzCore/QuartzCore.h>
14#include "flutter/common/graphics/persistent_cache.h"
15#include "flutter/fml/make_copyable.h"
16#include "flutter/fml/platform/darwin/cf_utils.h"
17#include "flutter/fml/platform/darwin/scoped_nsobject.h"
18#include "flutter/fml/trace_event.h"
19#include "flutter/shell/gpu/gpu_surface_metal_delegate.h"
36static_assert(!
__has_feature(objc_arc),
"ARC must be disabled.");
49 GrMtlTextureInfo
info;
54 std::move(color_space), props, release_proc,
61 bool render_to_surface)
63 render_target_type_(delegate->GetRenderTargetType()),
64 context_(
std::move(context)),
65 render_to_surface_(render_to_surface) {
67 NSNumber* disablePartialRepaint =
68 [[NSBundle mainBundle] objectForInfoDictionaryKey:
@"FLTDisablePartialRepaint"];
69 if (disablePartialRepaint != nil) {
70 disable_partial_repaint_ = disablePartialRepaint.boolValue;
78 return context_ !=
nullptr;
81void GPUSurfaceMetalSkia::PrecompileKnownSkSLsIfNecessary() {
92std::unique_ptr<SurfaceFrame> GPUSurfaceMetalSkia::AcquireFrame(
const SkISize& frame_size) {
99 FML_LOG(
ERROR) <<
"Metal surface was asked for an empty frame.";
103 if (!render_to_surface_) {
104 return std::make_unique<SurfaceFrame>(
105 nullptr, SurfaceFrame::FramebufferInfo(),
106 [](
const SurfaceFrame& surface_frame,
DlCanvas* canvas) {
return true; }, frame_size);
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(
127 FML_LOG(
ERROR) <<
"Invalid CAMetalLayer given by the embedder.";
131 auto* mtl_layer = (CAMetalLayer*)layer;
134 reinterpret_cast<id<CAMetalDrawable>
>([[mtl_layer nextDrawable] retain]));
136 if (!drawable.get()) {
137 FML_LOG(
ERROR) <<
"Could not obtain drawable from the metal layer.";
141 auto surface = CreateSurfaceFromMetalTexture(context_.
get(), drawable.get().texture,
151 FML_LOG(
ERROR) <<
"Could not create the SkSurface from the CAMetalLayer.";
155 auto submit_callback = [
this, drawable](
const SurfaceFrame& surface_frame,
158 if (canvas ==
nullptr) {
168 if (!disable_partial_repaint_) {
169 uintptr_t
texture =
reinterpret_cast<uintptr_t
>(drawable.get().texture);
170 for (
auto& entry : damage_) {
173 if (surface_frame.submit_info().frame_damage) {
174 entry.second.join(*surface_frame.submit_info().frame_damage);
185 SurfaceFrame::FramebufferInfo framebuffer_info;
186 framebuffer_info.supports_readback =
true;
188 if (!disable_partial_repaint_) {
191 uintptr_t
texture =
reinterpret_cast<uintptr_t
>(drawable.get().texture);
193 if (
i != damage_.end()) {
194 framebuffer_info.existing_damage =
i->second;
196 framebuffer_info.supports_partial_repaint =
true;
199 return std::make_unique<SurfaceFrame>(std::move(
surface), framebuffer_info, submit_callback,
203std::unique_ptr<SurfaceFrame> GPUSurfaceMetalSkia::AcquireFrameFromMTLTexture(
206 id<MTLTexture> mtl_texture = (id<MTLTexture>)(
texture.texture);
209 FML_LOG(
ERROR) <<
"Invalid MTLTexture given by the embedder.";
219 FML_LOG(
ERROR) <<
"Could not create the SkSurface from the metal texture.";
224 const SurfaceFrame& surface_frame,
DlCanvas* canvas) ->
bool {
225 TRACE_EVENT0(
"flutter",
"GPUSurfaceMetal::PresentTexture");
226 if (canvas ==
nullptr) {
236 return delegate->PresentTexture(
texture);
239 SurfaceFrame::FramebufferInfo framebuffer_info;
240 framebuffer_info.supports_readback =
true;
242 return std::make_unique<SurfaceFrame>(std::move(
surface), framebuffer_info, submit_callback,
247SkMatrix GPUSurfaceMetalSkia::GetRootTransformation()
const {
255 return context_.
get();
259std::unique_ptr<GLContextResult> GPUSurfaceMetalSkia::MakeRenderContextCurrent() {
262 PrecompileKnownSkSLsIfNecessary();
265 return std::make_unique<GLContextDefaultResult>(
true);
268bool GPUSurfaceMetalSkia::AllowsDrawingWhenGpuDisabled()
const {
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
@ kTopLeft_GrSurfaceOrigin
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
static PersistentCache * GetCacheForProcess()
size_t PrecompileKnownSkSLs(GrDirectContext *context) const
Precompile SkSLs packaged with the application and gathered during previous runs in the given context...
#define FML_DLOG(severity)
#define FML_LOG(severity)
#define FML_CHECK(condition)
SK_API GrBackendTexture MakeMtl(int width, int height, skgpu::Mipmapped, const GrMtlTextureInfo &mtlInfo, std::string_view label={})
SK_API sk_sp< SkSurface > WrapBackendTexture(GrRecordingContext *context, const GrBackendTexture &backendTexture, GrSurfaceOrigin origin, int sampleCnt, SkColorType colorType, sk_sp< SkColorSpace > colorSpace, const SkSurfaceProps *surfaceProps, TextureReleaseProc textureReleaseProc=nullptr, ReleaseContext releaseContext=nullptr)
void(*)(ReleaseContext) TextureReleaseProc
static thread_local std::unique_ptr< int > current_context
flutter::DlCanvas DlCanvas
static constexpr SkIRect MakeEmpty()
#define TRACE_EVENT0(category_group, name)