5#include "flutter/shell/gpu/gpu_surface_metal_skia.h"
8#import <QuartzCore/QuartzCore.h>
12#include "flutter/common/graphics/persistent_cache.h"
13#include "flutter/fml/make_copyable.h"
14#include "flutter/fml/platform/darwin/cf_utils.h"
15#include "flutter/fml/platform/darwin/scoped_nsobject.h"
16#include "flutter/fml/trace_event.h"
17#include "flutter/shell/gpu/gpu_surface_metal_delegate.h"
34static_assert(!
__has_feature(objc_arc),
"ARC must be disabled.");
48 GrMtlTextureInfo
info;
53 context, backend_texture, origin,
static_cast<int>(sample_cnt),
color_type,
54 std::move(color_space), props, release_proc, release_context);
61 bool render_to_surface)
63 render_target_type_(delegate->GetRenderTargetType()),
64 context_(
std::move(context)),
65 msaa_samples_(msaa_samples),
66 render_to_surface_(render_to_surface) {
68 NSNumber* disablePartialRepaint =
69 [[NSBundle mainBundle] objectForInfoDictionaryKey:
@"FLTDisablePartialRepaint"];
70 if (disablePartialRepaint != nil) {
71 disable_partial_repaint_ = disablePartialRepaint.boolValue;
79 return context_ !=
nullptr;
82void GPUSurfaceMetalSkia::PrecompileKnownSkSLsIfNecessary() {
84 if (current_context == precompiled_sksl_context_) {
88 precompiled_sksl_context_ = current_context;
100 FML_LOG(
ERROR) <<
"Metal surface was asked for an empty frame.";
104 if (!render_to_surface_) {
105 return std::make_unique<SurfaceFrame>(
110 PrecompileKnownSkSLsIfNecessary();
112 switch (render_target_type_) {
114 return AcquireFrameFromCAMetalLayer(frame_size);
116 return AcquireFrameFromMTLTexture(frame_size);
118 FML_CHECK(
false) <<
"Unknown MTLRenderTargetType type.";
124std::unique_ptr<SurfaceFrame> GPUSurfaceMetalSkia::AcquireFrameFromCAMetalLayer(
128 FML_LOG(
ERROR) <<
"Invalid CAMetalLayer given by the embedder.";
132 auto* mtl_layer = (CAMetalLayer*)layer;
135 reinterpret_cast<id<CAMetalDrawable>
>([[mtl_layer nextDrawable] retain]));
137 if (!drawable.get()) {
138 FML_LOG(
ERROR) <<
"Could not obtain drawable from the metal layer.";
142 auto surface = CreateSurfaceFromMetalTexture(context_.
get(), drawable.get().texture,
153 FML_LOG(
ERROR) <<
"Could not create the SkSurface from the CAMetalLayer.";
157 auto submit_callback = [
this, drawable](
const SurfaceFrame& surface_frame,
158 DlCanvas* canvas) ->
bool {
160 if (canvas ==
nullptr) {
170 if (!disable_partial_repaint_) {
171 uintptr_t
texture =
reinterpret_cast<uintptr_t
>(drawable.get().texture);
172 for (
auto& entry : damage_) {
175 if (surface_frame.submit_info().frame_damage) {
176 entry.second.join(*surface_frame.submit_info().frame_damage);
187 SurfaceFrame::FramebufferInfo framebuffer_info;
188 framebuffer_info.supports_readback =
true;
190 if (!disable_partial_repaint_) {
193 uintptr_t
texture =
reinterpret_cast<uintptr_t
>(drawable.get().texture);
194 auto i = damage_.find(
texture);
195 if (i != damage_.end()) {
196 framebuffer_info.existing_damage = i->second;
198 framebuffer_info.supports_partial_repaint =
true;
201 return std::make_unique<SurfaceFrame>(std::move(
surface), framebuffer_info, submit_callback,
205std::unique_ptr<SurfaceFrame> GPUSurfaceMetalSkia::AcquireFrameFromMTLTexture(
208 id<MTLTexture> mtl_texture = (id<MTLTexture>)(
texture.texture);
211 FML_LOG(
ERROR) <<
"Invalid MTLTexture given by the embedder.";
221 FML_LOG(
ERROR) <<
"Could not create the SkSurface from the metal texture.";
226 const SurfaceFrame& surface_frame, DlCanvas* canvas) ->
bool {
227 TRACE_EVENT0(
"flutter",
"GPUSurfaceMetal::PresentTexture");
228 if (canvas ==
nullptr) {
238 return delegate->PresentTexture(
texture);
241 SurfaceFrame::FramebufferInfo framebuffer_info;
242 framebuffer_info.supports_readback =
true;
244 return std::make_unique<SurfaceFrame>(std::move(
surface), framebuffer_info, submit_callback,
257 return context_.
get();
264 PrecompileKnownSkSLsIfNecessary();
267 return std::make_unique<GLContextDefaultResult>(
true);
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
Developer-facing API for rendering anything within the engine.
static PersistentCache * GetCacheForProcess()
size_t PrecompileKnownSkSLs(GrDirectContext *context) const
Precompile SkSLs packaged with the application and gathered during previous runs in the given context...
void reset(T *ptr=nullptr)
#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 constexpr SkIRect MakeEmpty()
#define TRACE_EVENT0(category_group, name)