Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
sxychenjing
engine
提交
a322e69b
E
engine
项目概览
sxychenjing
/
engine
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
E
engine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
a322e69b
编写于
2月 11, 2021
作者:
K
Kaushik Iska
提交者:
GitHub
2月 11, 2021
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Reland "[metal] Darwin unified external metal textures (#24157)" (#24350)
上级
011b5abb
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
380 addition
and
268 deletion
+380
-268
README.md
README.md
+1
-0
ci/licenses_golden/licenses_flutter
ci/licenses_golden/licenses_flutter
+2
-0
common/config.gni
common/config.gni
+2
-0
common/graphics/texture.h
common/graphics/texture.h
+2
-2
shell/platform/darwin/graphics/BUILD.gn
shell/platform/darwin/graphics/BUILD.gn
+7
-2
shell/platform/darwin/graphics/FlutterDarwinContextMetal.h
shell/platform/darwin/graphics/FlutterDarwinContextMetal.h
+15
-0
shell/platform/darwin/graphics/FlutterDarwinContextMetal.mm
shell/platform/darwin/graphics/FlutterDarwinContextMetal.mm
+39
-10
shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.h
...tform/darwin/graphics/FlutterDarwinExternalTextureMetal.h
+34
-0
shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.mm
...form/darwin/graphics/FlutterDarwinExternalTextureMetal.mm
+254
-0
shell/platform/darwin/ios/ios_context_metal.mm
shell/platform/darwin/ios/ios_context_metal.mm
+4
-1
shell/platform/darwin/ios/ios_external_texture_metal.h
shell/platform/darwin/ios/ios_external_texture_metal.h
+6
-23
shell/platform/darwin/ios/ios_external_texture_metal.mm
shell/platform/darwin/ios/ios_external_texture_metal.mm
+12
-228
shell/platform/darwin/macos/BUILD.gn
shell/platform/darwin/macos/BUILD.gn
+2
-2
未找到文件。
README.md
浏览文件 @
a322e69b
...
...
@@ -30,5 +30,6 @@ Information on how to get started can be found at our
[
contributor guide
](
CONTRIBUTING.md
)
.
[
Build Status - Cirrus
]:
https://api.cirrus-ci.com/github/flutter/engine.svg?branch=master
[
Build status
]:
https://cirrus-ci.com/github/flutter/engine
ci/licenses_golden/licenses_flutter
浏览文件 @
a322e69b
...
...
@@ -969,6 +969,8 @@ FILE: ../../../flutter/shell/platform/darwin/common/framework/Source/flutter_cod
FILE: ../../../flutter/shell/platform/darwin/common/framework/Source/flutter_standard_codec_unittest.mm
FILE: ../../../flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetal.h
FILE: ../../../flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetal.mm
FILE: ../../../flutter/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.h
FILE: ../../../flutter/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Flutter.podspec
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/Flutter.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterAppDelegate.h
...
...
common/config.gni
浏览文件 @
a322e69b
...
...
@@ -62,4 +62,6 @@ if (is_ios || is_mac) {
"-Werror=undeclared-selector",
]
flutter_cflags_objcc = flutter_cflags_objc
flutter_cflags_objc_arc = flutter_cflags_objc + [ "-fobjc-arc" ]
flutter_cflags_objcc_arc = flutter_cflags_objc_arc
}
common/graphics/texture.h
浏览文件 @
a322e69b
...
...
@@ -18,8 +18,8 @@ namespace flutter {
class
Texture
{
public:
Texture
(
int64_t
id
);
// Called from UI or raster thread.
virtual
~
Texture
();
// Called from raster thread.
explicit
Texture
(
int64_t
id
);
// Called from UI or raster thread.
virtual
~
Texture
();
// Called from raster thread.
// Called from raster thread.
virtual
void
Paint
(
SkCanvas
&
canvas
,
...
...
shell/platform/darwin/graphics/BUILD.gn
浏览文件 @
a322e69b
...
...
@@ -7,19 +7,24 @@ assert(is_ios || is_mac)
import("//flutter/common/config.gni")
source_set("graphics") {
cflags_objc = flutter_cflags_objc
cflags_objcc = flutter_cflags_objcc
cflags_objc = flutter_cflags_objc
_arc
cflags_objcc = flutter_cflags_objcc
_arc
sources = [
"FlutterDarwinContextMetal.h",
"FlutterDarwinContextMetal.mm",
"FlutterDarwinExternalTextureMetal.h",
"FlutterDarwinExternalTextureMetal.mm",
]
deps = [
"//flutter/common/graphics",
"//flutter/fml",
"//flutter/shell/platform/darwin/common:framework_shared",
]
libs = [ "CoreVideo.framework" ]
public_deps = [ "//third_party/skia" ]
public_configs = [ "//flutter:config" ]
...
...
shell/platform/darwin/graphics/FlutterDarwinContextMetal.h
浏览文件 @
a322e69b
...
...
@@ -5,9 +5,12 @@
#ifndef SHELL_PLATFORM_DARWIN_GRAPHICS_DARWIN_CONTEXT_METAL_H_
#define SHELL_PLATFORM_DARWIN_GRAPHICS_DARWIN_CONTEXT_METAL_H_
#import <CoreVideo/CVMetalTextureCache.h>
#import <Foundation/Foundation.h>
#import <Metal/Metal.h>
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterTexture.h"
#import "flutter/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
NS_ASSUME_NONNULL_BEGIN
...
...
@@ -29,6 +32,13 @@ NS_ASSUME_NONNULL_BEGIN
-
(
instancetype
)
initWithMTLDevice
:(
id
<
MTLDevice
>
)
device
commandQueue
:(
id
<
MTLCommandQueue
>
)
commandQueue
;
/**
* Creates an external texture with the specified ID and contents.
*/
-
(
FlutterDarwinExternalTextureMetal
*
)
createExternalTextureWithIdentifier
:(
int64_t
)
textureID
texture
:(
NSObject
<
FlutterTexture
>*
)
texture
;
/**
* MTLDevice that is backing this context.s
*/
...
...
@@ -50,6 +60,11 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property
(
nonatomic
,
readonly
)
sk_sp
<
GrDirectContext
>
resourceContext
;
/*
* Texture cache for external textures.
*/
@property
(
nonatomic
,
readonly
)
CVMetalTextureCacheRef
textureCache
;
@end
NS_ASSUME_NONNULL_END
...
...
shell/platform/darwin/graphics/FlutterDarwinContextMetal.mm
浏览文件 @
a322e69b
...
...
@@ -6,8 +6,11 @@
#include "flutter/common/graphics/persistent_cache.h"
#include "flutter/fml/logging.h"
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h"
#include "third_party/skia/include/gpu/GrContextOptions.h"
FLUTTER_ASSERT_ARC
static
GrContextOptions
CreateMetalGrContextOptions
()
{
GrContextOptions
options
=
{};
if
(
flutter
::
PersistentCache
::
cache_sksl
())
{
...
...
@@ -33,7 +36,6 @@ static GrContextOptions CreateMetalGrContextOptions() {
if
(
!
_device
)
{
FML_DLOG
(
ERROR
)
<<
"Could not acquire Metal device."
;
[
self
release
];
return
nil
;
}
...
...
@@ -41,24 +43,27 @@ static GrContextOptions CreateMetalGrContextOptions() {
if
(
!
_commandQueue
)
{
FML_DLOG
(
ERROR
)
<<
"Could not create Metal command queue."
;
[
self
release
];
return
nil
;
}
[
_commandQueue
setLabel
:
@"Flutter Main Queue"
];
auto
contextOptions
=
CreateMetalGrContextOptions
();
CVReturn
cvReturn
=
CVMetalTextureCacheCreate
(
kCFAllocatorDefault
,
// allocator
nil
,
// cache attributes (nil default)
_device
,
// metal device
nil
,
// texture attributes (nil default)
&
_textureCache
// [out] cache
);
if
(
cvReturn
!=
kCVReturnSuccess
)
{
FML_DLOG
(
ERROR
)
<<
"Could not create Metal texture cache."
;
return
nil
;
}
// Skia expect arguments to `MakeMetal` transfer ownership of the reference in for release later
// when the GrDirectContext is collected.
_mainContext
=
GrDirectContext
::
MakeMetal
([
_device
retain
],
[
_commandQueue
retain
],
contextOptions
);
_resourceContext
=
GrDirectContext
::
MakeMetal
([
_device
retain
],
[
_commandQueue
retain
],
contextOptions
);
_mainContext
=
[
self
createGrContext
];
_resourceContext
=
[
self
createGrContext
];
if
(
!
_mainContext
||
!
_resourceContext
)
{
FML_DLOG
(
ERROR
)
<<
"Could not create Skia Metal contexts."
;
[
self
release
];
return
nil
;
}
...
...
@@ -67,4 +72,28 @@ static GrContextOptions CreateMetalGrContextOptions() {
return
self
;
}
-
(
sk_sp
<
GrDirectContext
>
)
createGrContext
{
auto
contextOptions
=
CreateMetalGrContextOptions
();
id
<
MTLDevice
>
device
=
_device
;
id
<
MTLCommandQueue
>
commandQueue
=
_commandQueue
;
// Skia expect arguments to `MakeMetal` transfer ownership of the reference in for release later
// when the GrDirectContext is collected.
return
GrDirectContext
::
MakeMetal
((
__bridge_retained
void
*
)
device
,
(
__bridge_retained
void
*
)
commandQueue
,
contextOptions
);
}
-
(
void
)
dealloc
{
if
(
_textureCache
)
{
CFRelease
(
_textureCache
);
}
}
-
(
FlutterDarwinExternalTextureMetal
*
)
createExternalTextureWithIdentifier
:(
int64_t
)
textureID
texture
:(
NSObject
<
FlutterTexture
>*
)
texture
{
return
[[
FlutterDarwinExternalTextureMetal
alloc
]
initWithTextureCache
:
_textureCache
textureID:
textureID
texture:
texture
];
}
@end
shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.h
0 → 100644
浏览文件 @
a322e69b
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <Foundation/Foundation.h>
#import <Metal/Metal.h>
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterTexture.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
@interface
FlutterDarwinExternalTextureMetal
:
NSObject
-
(
nullable
instancetype
)
initWithTextureCache
:(
nonnull
CVMetalTextureCacheRef
)
textureCache
textureID
:(
int64_t
)
textureID
texture
:(
nonnull
NSObject
<
FlutterTexture
>*
)
texture
;
-
(
void
)
paint
:(
SkCanvas
&
)
canvas
bounds
:(
const
SkRect
&
)
bounds
freeze
:(
BOOL
)
freeze
grContext
:(
nonnull
GrDirectContext
*
)
grContext
sampling
:(
const
SkSamplingOptions
&
)
sampling
;
-
(
void
)
onGrContextCreated
;
-
(
void
)
onGrContextDestroyed
;
-
(
void
)
markNewFrameAvailable
;
-
(
void
)
onTextureUnregistered
;
@property
(
nonatomic
,
readonly
)
int64_t
textureID
;
@end
shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.mm
0 → 100644
浏览文件 @
a322e69b
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "flutter/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.h"
#include "flutter/fml/logging.h"
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h"
#include "third_party/skia/include/core/SkYUVAInfo.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
#include "third_party/skia/include/gpu/GrYUVABackendTextures.h"
#include "third_party/skia/include/gpu/mtl/GrMtlTypes.h"
FLUTTER_ASSERT_ARC
namespace
{
static
sk_cf_obj
<
const
void
*>
SkiaTextureFromCVMetalTexture
(
CVMetalTextureRef
cvMetalTexture
)
{
id
<
MTLTexture
>
texture
=
CVMetalTextureGetTexture
(
cvMetalTexture
);
// CVMetal texture can be released as soon as we can the MTLTexture from it.
CVPixelBufferRelease
(
cvMetalTexture
);
return
sk_cf_obj
<
const
void
*>
{(
__bridge_retained
const
void
*
)
texture
};
}
}
@implementation
FlutterDarwinExternalTextureMetal
{
CVMetalTextureCacheRef
_textureCache
;
NSObject
<
FlutterTexture
>*
_externalTexture
;
BOOL
_textureFrameAvailable
;
sk_sp
<
SkImage
>
_externalImage
;
CVPixelBufferRef
_lastPixelBuffer
;
OSType
_pixelFormat
;
}
-
(
instancetype
)
initWithTextureCache
:(
nonnull
CVMetalTextureCacheRef
)
textureCache
textureID
:(
int64_t
)
textureID
texture
:(
NSObject
<
FlutterTexture
>*
)
texture
{
if
(
self
=
[
super
init
])
{
_textureCache
=
textureCache
;
CFRetain
(
_textureCache
);
_textureID
=
textureID
;
_externalTexture
=
texture
;
return
self
;
}
return
nil
;
}
-
(
void
)
dealloc
{
CVPixelBufferRelease
(
_lastPixelBuffer
);
if
(
_textureCache
)
{
CFRelease
(
_textureCache
);
}
}
-
(
void
)
paint
:(
SkCanvas
&
)
canvas
bounds
:(
const
SkRect
&
)
bounds
freeze
:(
BOOL
)
freeze
grContext
:(
nonnull
GrDirectContext
*
)
grContext
sampling
:(
const
SkSamplingOptions
&
)
sampling
{
const
bool
needsUpdatedTexture
=
(
!
freeze
&&
_textureFrameAvailable
)
||
!
_externalImage
;
if
(
needsUpdatedTexture
)
{
[
self
onNeedsUpdatedTexture
:
grContext
];
}
if
(
_externalImage
)
{
canvas
.
drawImageRect
(
_externalImage
,
// image
SkRect
::
Make
(
_externalImage
->
bounds
()),
// source rect
bounds
,
// destination rect
sampling
,
// sampling
nullptr
,
// paint
SkCanvas
::
SrcRectConstraint
::
kFast_SrcRectConstraint
// constraint
);
}
}
-
(
void
)
onNeedsUpdatedTexture
:(
nonnull
GrDirectContext
*
)
grContext
{
CVPixelBufferRef
pixelBuffer
=
[
_externalTexture
copyPixelBuffer
];
if
(
pixelBuffer
)
{
CVPixelBufferRelease
(
_lastPixelBuffer
);
_lastPixelBuffer
=
pixelBuffer
;
_pixelFormat
=
CVPixelBufferGetPixelFormatType
(
_lastPixelBuffer
);
}
// If the application told us there was a texture frame available but did not provide one when
// asked for it, reuse the previous texture but make sure to ask again the next time around.
sk_sp
<
SkImage
>
image
=
[
self
wrapExternalPixelBuffer
:
_lastPixelBuffer
grContext
:
grContext
];
if
(
image
)
{
_externalImage
=
image
;
_textureFrameAvailable
=
false
;
}
}
-
(
void
)
onGrContextCreated
{
// External images in this backend have no thread affinity and are not tied to the context in any
// way. Instead, they are tied to the Metal device which is associated with the cache already and
// is consistent throughout the shell run.
}
-
(
void
)
onGrContextDestroyed
{
// The image must be reset because it is tied to the onscreen context. But the pixel buffer that
// created the image is still around. In case of context reacquisition, that last pixel
// buffer will be used to materialize the image in case the application fails to provide a new
// one.
_externalImage
.
reset
();
CVMetalTextureCacheFlush
(
_textureCache
,
// cache
0
// options (must be zero)
);
}
-
(
void
)
markNewFrameAvailable
{
_textureFrameAvailable
=
YES
;
}
-
(
void
)
onTextureUnregistered
{
if
([
_externalTexture
respondsToSelector
:
@selector
(
onTextureUnregistered
:)])
{
[
_externalTexture
onTextureUnregistered
:
_externalTexture
];
}
}
#pragma mark - External texture skia wrapper methods.
-
(
sk_sp
<
SkImage
>
)
wrapExternalPixelBuffer
:(
CVPixelBufferRef
)
pixelBuffer
grContext
:(
GrDirectContext
*
)
grContext
{
if
(
!
pixelBuffer
)
{
return
nullptr
;
}
sk_sp
<
SkImage
>
image
=
nullptr
;
if
(
_pixelFormat
==
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
||
_pixelFormat
==
kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
)
{
image
=
[
self
wrapNV12ExternalPixelBuffer
:
pixelBuffer
grContext
:
grContext
];
}
else
{
image
=
[
self
wrapRGBAExternalPixelBuffer
:
pixelBuffer
grContext
:
grContext
];
}
if
(
!
image
)
{
FML_DLOG
(
ERROR
)
<<
"Could not wrap Metal texture as a Skia image."
;
}
return
image
;
}
-
(
sk_sp
<
SkImage
>
)
wrapNV12ExternalPixelBuffer
:(
CVPixelBufferRef
)
pixelBuffer
grContext
:(
GrDirectContext
*
)
grContext
{
SkISize
textureSize
=
SkISize
::
Make
(
CVPixelBufferGetWidth
(
pixelBuffer
),
CVPixelBufferGetHeight
(
pixelBuffer
));
CVMetalTextureRef
yMetalTexture
=
nullptr
;
{
CVReturn
cvReturn
=
CVMetalTextureCacheCreateTextureFromImage
(
/*allocator=*/
kCFAllocatorDefault
,
/*textureCache=*/
_textureCache
,
/*sourceImage=*/
pixelBuffer
,
/*textureAttributes=*/
nullptr
,
/*pixelFormat=*/
MTLPixelFormatR8Unorm
,
/*width=*/
textureSize
.
width
(),
/*height=*/
textureSize
.
height
(),
/*planeIndex=*/
0u
,
/*texture=*/
&
yMetalTexture
);
if
(
cvReturn
!=
kCVReturnSuccess
)
{
FML_DLOG
(
ERROR
)
<<
"Could not create Metal texture from pixel buffer: CVReturn "
<<
cvReturn
;
return
nullptr
;
}
}
CVMetalTextureRef
uvMetalTexture
=
nullptr
;
{
CVReturn
cvReturn
=
CVMetalTextureCacheCreateTextureFromImage
(
/*allocator=*/
kCFAllocatorDefault
,
/*textureCache=*/
_textureCache
,
/*sourceImage=*/
pixelBuffer
,
/*textureAttributes=*/
nullptr
,
/*pixelFormat=*/
MTLPixelFormatRG8Unorm
,
/*width=*/
textureSize
.
width
()
/
2
,
/*height=*/
textureSize
.
height
()
/
2
,
/*planeIndex=*/
1u
,
/*texture=*/
&
uvMetalTexture
);
if
(
cvReturn
!=
kCVReturnSuccess
)
{
FML_DLOG
(
ERROR
)
<<
"Could not create Metal texture from pixel buffer: CVReturn "
<<
cvReturn
;
return
nullptr
;
}
}
GrMtlTextureInfo
ySkiaTextureInfo
;
ySkiaTextureInfo
.
fTexture
=
SkiaTextureFromCVMetalTexture
(
yMetalTexture
);
GrBackendTexture
skiaBackendTextures
[
2
];
skiaBackendTextures
[
0
]
=
GrBackendTexture
(
/*width=*/
textureSize
.
width
(),
/*height=*/
textureSize
.
height
(),
/*mipMapped=*/
GrMipMapped
::
kNo
,
/*textureInfo=*/
ySkiaTextureInfo
);
GrMtlTextureInfo
uvSkiaTextureInfo
;
uvSkiaTextureInfo
.
fTexture
=
SkiaTextureFromCVMetalTexture
(
uvMetalTexture
);
skiaBackendTextures
[
1
]
=
GrBackendTexture
(
/*width=*/
textureSize
.
width
(),
/*height=*/
textureSize
.
height
(),
/*mipMapped=*/
GrMipMapped
::
kNo
,
/*textureInfo=*/
uvSkiaTextureInfo
);
SkYUVAInfo
yuvaInfo
(
skiaBackendTextures
[
0
].
dimensions
(),
SkYUVAInfo
::
PlaneConfig
::
kY_UV
,
SkYUVAInfo
::
Subsampling
::
k444
,
kRec601_SkYUVColorSpace
);
GrYUVABackendTextures
yuvaBackendTextures
(
yuvaInfo
,
skiaBackendTextures
,
kTopLeft_GrSurfaceOrigin
);
sk_sp
<
SkImage
>
image
=
SkImage
::
MakeFromYUVATextures
(
grContext
,
yuvaBackendTextures
,
/*imageColorSpace=*/
nullptr
,
/*releaseProc*/
nullptr
,
/*releaseContext*/
nullptr
);
return
image
;
}
-
(
sk_sp
<
SkImage
>
)
wrapRGBAExternalPixelBuffer
:(
CVPixelBufferRef
)
pixelBuffer
grContext
:(
GrDirectContext
*
)
grContext
{
SkISize
textureSize
=
SkISize
::
Make
(
CVPixelBufferGetWidth
(
pixelBuffer
),
CVPixelBufferGetHeight
(
pixelBuffer
));
CVMetalTextureRef
metalTexture
=
nullptr
;
CVReturn
cvReturn
=
CVMetalTextureCacheCreateTextureFromImage
(
/*allocator=*/
kCFAllocatorDefault
,
/*textureCache=*/
_textureCache
,
/*sourceImage=*/
pixelBuffer
,
/*textureAttributes=*/
nullptr
,
/*pixelFormat=*/
MTLPixelFormatBGRA8Unorm
,
/*width=*/
textureSize
.
width
(),
/*height=*/
textureSize
.
height
(),
/*planeIndex=*/
0u
,
/*texture=*/
&
metalTexture
);
if
(
cvReturn
!=
kCVReturnSuccess
)
{
FML_DLOG
(
ERROR
)
<<
"Could not create Metal texture from pixel buffer: CVReturn "
<<
cvReturn
;
return
nullptr
;
}
GrMtlTextureInfo
skiaTextureInfo
;
skiaTextureInfo
.
fTexture
=
SkiaTextureFromCVMetalTexture
(
metalTexture
);
GrBackendTexture
skiaBackendTexture
(
/*width=*/
textureSize
.
width
(),
/*height=*/
textureSize
.
height
(),
/*mipMapped=*/
GrMipMapped
::
kNo
,
/*textureInfo=*/
skiaTextureInfo
);
sk_sp
<
SkImage
>
image
=
SkImage
::
MakeFromTexture
(
grContext
,
skiaBackendTexture
,
kTopLeft_GrSurfaceOrigin
,
kBGRA_8888_SkColorType
,
kPremul_SkAlphaType
,
/*imageColorSpace=*/
nullptr
,
/*releaseProc*/
nullptr
,
/*releaseContext*/
nullptr
);
return
image
;
}
@end
shell/platform/darwin/ios/ios_context_metal.mm
浏览文件 @
a322e69b
...
...
@@ -65,7 +65,10 @@ std::unique_ptr<GLContextResult> IOSContextMetal::MakeCurrent() {
std
::
unique_ptr
<
Texture
>
IOSContextMetal
::
CreateExternalTexture
(
int64_t
texture_id
,
fml
::
scoped_nsobject
<
NSObject
<
FlutterTexture
>>
texture
)
{
return
std
::
make_unique
<
IOSExternalTextureMetal
>
(
texture_id
,
texture_cache_
,
std
::
move
(
texture
));
return
std
::
make_unique
<
IOSExternalTextureMetal
>
(
fml
::
scoped_nsobject
<
FlutterDarwinExternalTextureMetal
>
{
[[
darwin_context_metal_
createExternalTextureWithIdentifier
:
texture_id
texture:
texture
]
retain
]});
}
}
// namespace flutter
shell/platform/darwin/ios/ios_external_texture_metal.h
浏览文件 @
a322e69b
...
...
@@ -5,35 +5,25 @@
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_EXTERNAL_TEXTURE_METAL_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_EXTERNAL_TEXTURE_METAL_H_
#include <atomic>
#import <CoreVideo/CoreVideo.h>
#include "flutter/common/graphics/texture.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/platform/darwin/cf_utils.h"
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterTexture.h"
#include "third_party/skia/include/core/SkImage.h"
#import "flutter/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.h"
namespace
flutter
{
class
IOSExternalTextureMetal
final
:
public
Texture
{
public:
IOSExternalTextureMetal
(
int64_t
texture_id
,
fml
::
CFRef
<
CVMetalTextureCacheRef
>
texture_cache
,
fml
::
scoped_nsobject
<
NSObject
<
FlutterTexture
>>
external_texture
);
explicit
IOSExternalTextureMetal
(
fml
::
scoped_nsobject
<
FlutterDarwinExternalTextureMetal
>
darwin_external_texture_metal
);
// |Texture|
~
IOSExternalTextureMetal
();
private:
fml
::
CFRef
<
CVMetalTextureCacheRef
>
texture_cache_
;
fml
::
scoped_nsobject
<
NSObject
<
FlutterTexture
>>
external_texture_
;
std
::
atomic_bool
texture_frame_available_
;
fml
::
CFRef
<
CVPixelBufferRef
>
last_pixel_buffer_
;
sk_sp
<
SkImage
>
external_image_
;
OSType
pixel_format_
=
0
;
fml
::
scoped_nsobject
<
FlutterDarwinExternalTextureMetal
>
darwin_external_texture_metal_
;
// |Texture|
void
Paint
(
SkCanvas
&
canvas
,
...
...
@@ -54,13 +44,6 @@ class IOSExternalTextureMetal final : public Texture {
// |Texture|
void
OnTextureUnregistered
()
override
;
sk_sp
<
SkImage
>
WrapExternalPixelBuffer
(
fml
::
CFRef
<
CVPixelBufferRef
>
pixel_buffer
,
GrDirectContext
*
context
)
const
;
sk_sp
<
SkImage
>
WrapRGBAExternalPixelBuffer
(
fml
::
CFRef
<
CVPixelBufferRef
>
pixel_buffer
,
GrDirectContext
*
context
)
const
;
sk_sp
<
SkImage
>
WrapNV12ExternalPixelBuffer
(
fml
::
CFRef
<
CVPixelBufferRef
>
pixel_buffer
,
GrDirectContext
*
context
)
const
;
FML_DISALLOW_COPY_AND_ASSIGN
(
IOSExternalTextureMetal
);
};
...
...
shell/platform/darwin/ios/ios_external_texture_metal.mm
浏览文件 @
a322e69b
...
...
@@ -4,25 +4,12 @@
#import "flutter/shell/platform/darwin/ios/ios_external_texture_metal.h"
#include "flutter/fml/logging.h"
#include "third_party/skia/include/core/SkYUVAInfo.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
#include "third_party/skia/include/gpu/GrYUVABackendTextures.h"
#include "third_party/skia/include/gpu/mtl/GrMtlTypes.h"
namespace
flutter
{
IOSExternalTextureMetal
::
IOSExternalTextureMetal
(
int64_t
texture_id
,
fml
::
CFRef
<
CVMetalTextureCacheRef
>
texture_cache
,
fml
::
scoped_nsobject
<
NSObject
<
FlutterTexture
>>
external_texture
)
:
Texture
(
texture_id
),
texture_cache_
(
std
::
move
(
texture_cache
)),
external_texture_
(
std
::
move
(
external_texture
))
{
FML_DCHECK
(
texture_cache_
);
FML_DCHECK
(
external_texture_
);
}
fml
::
scoped_nsobject
<
FlutterDarwinExternalTextureMetal
>
darwin_external_texture_metal
)
:
Texture
([
darwin_external_texture_metal
textureID
]),
darwin_external_texture_metal_
(
darwin_external_texture_metal
)
{}
IOSExternalTextureMetal
::~
IOSExternalTextureMetal
()
=
default
;
...
...
@@ -31,230 +18,27 @@ void IOSExternalTextureMetal::Paint(SkCanvas& canvas,
bool
freeze
,
GrDirectContext
*
context
,
const
SkSamplingOptions
&
sampling
)
{
const
bool
needs_updated_texture
=
(
!
freeze
&&
texture_frame_available_
)
||
!
external_image_
;
if
(
needs_updated_texture
)
{
auto
pixel_buffer
=
fml
::
CFRef
<
CVPixelBufferRef
>
([
external_texture_
copyPixelBuffer
]);
if
(
!
pixel_buffer
)
{
pixel_buffer
=
std
::
move
(
last_pixel_buffer_
);
}
else
{
pixel_format_
=
CVPixelBufferGetPixelFormatType
(
pixel_buffer
);
}
// If the application told us there was a texture frame available but did not provide one when
// asked for it, reuse the previous texture but make sure to ask again the next time around.
if
(
auto
wrapped_texture
=
WrapExternalPixelBuffer
(
pixel_buffer
,
context
))
{
external_image_
=
wrapped_texture
;
texture_frame_available_
=
false
;
last_pixel_buffer_
=
std
::
move
(
pixel_buffer
);
}
}
if
(
external_image_
)
{
canvas
.
drawImageRect
(
external_image_
,
// image
SkRect
::
Make
(
external_image_
->
bounds
()),
// source rect
bounds
,
// destination rect
sampling
,
nullptr
,
// paint
SkCanvas
::
SrcRectConstraint
::
kFast_SrcRectConstraint
// constraint
);
}
}
sk_sp
<
SkImage
>
IOSExternalTextureMetal
::
WrapExternalPixelBuffer
(
fml
::
CFRef
<
CVPixelBufferRef
>
pixel_buffer
,
GrDirectContext
*
context
)
const
{
if
(
!
pixel_buffer
)
{
return
nullptr
;
}
sk_sp
<
SkImage
>
image
=
nullptr
;
if
(
pixel_format_
==
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
||
pixel_format_
==
kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
)
{
image
=
WrapNV12ExternalPixelBuffer
(
pixel_buffer
,
context
);
}
else
{
image
=
WrapRGBAExternalPixelBuffer
(
pixel_buffer
,
context
);
}
if
(
!
image
)
{
FML_DLOG
(
ERROR
)
<<
"Could not wrap Metal texture as a Skia image."
;
}
return
image
;
}
sk_sp
<
SkImage
>
IOSExternalTextureMetal
::
WrapNV12ExternalPixelBuffer
(
fml
::
CFRef
<
CVPixelBufferRef
>
pixel_buffer
,
GrDirectContext
*
context
)
const
{
auto
texture_size
=
SkISize
::
Make
(
CVPixelBufferGetWidth
(
pixel_buffer
),
CVPixelBufferGetHeight
(
pixel_buffer
));
CVMetalTextureRef
y_metal_texture_raw
=
nullptr
;
{
auto
cv_return
=
CVMetalTextureCacheCreateTextureFromImage
(
/*allocator=*/
kCFAllocatorDefault
,
/*textureCache=*/
texture_cache_
,
/*sourceImage=*/
pixel_buffer
,
/*textureAttributes=*/
nullptr
,
/*pixelFormat=*/
MTLPixelFormatR8Unorm
,
/*width=*/
texture_size
.
width
(),
/*height=*/
texture_size
.
height
(),
/*planeIndex=*/
0u
,
/*texture=*/
&
y_metal_texture_raw
);
if
(
cv_return
!=
kCVReturnSuccess
)
{
FML_DLOG
(
ERROR
)
<<
"Could not create Metal texture from pixel buffer: CVReturn "
<<
cv_return
;
return
nullptr
;
}
}
CVMetalTextureRef
uv_metal_texture_raw
=
nullptr
;
{
auto
cv_return
=
CVMetalTextureCacheCreateTextureFromImage
(
/*allocator=*/
kCFAllocatorDefault
,
/*textureCache=*/
texture_cache_
,
/*sourceImage=*/
pixel_buffer
,
/*textureAttributes=*/
nullptr
,
/*pixelFormat=*/
MTLPixelFormatRG8Unorm
,
/*width=*/
texture_size
.
width
()
/
2
,
/*height=*/
texture_size
.
height
()
/
2
,
/*planeIndex=*/
1u
,
/*texture=*/
&
uv_metal_texture_raw
);
if
(
cv_return
!=
kCVReturnSuccess
)
{
FML_DLOG
(
ERROR
)
<<
"Could not create Metal texture from pixel buffer: CVReturn "
<<
cv_return
;
return
nullptr
;
}
}
fml
::
CFRef
<
CVMetalTextureRef
>
y_metal_texture
(
y_metal_texture_raw
);
GrMtlTextureInfo
y_skia_texture_info
;
y_skia_texture_info
.
fTexture
=
sk_cf_obj
<
const
void
*>
{
[
reinterpret_cast
<
NSObject
*>
(
CVMetalTextureGetTexture
(
y_metal_texture
))
retain
]};
GrBackendTexture
skia_backend_textures
[
2
];
skia_backend_textures
[
0
]
=
GrBackendTexture
(
/*width=*/
texture_size
.
width
(),
/*height=*/
texture_size
.
height
(),
/*mipMapped=*/
GrMipMapped
::
kNo
,
/*textureInfo=*/
y_skia_texture_info
);
fml
::
CFRef
<
CVMetalTextureRef
>
uv_metal_texture
(
uv_metal_texture_raw
);
GrMtlTextureInfo
uv_skia_texture_info
;
uv_skia_texture_info
.
fTexture
=
sk_cf_obj
<
const
void
*>
{
[
reinterpret_cast
<
NSObject
*>
(
CVMetalTextureGetTexture
(
uv_metal_texture
))
retain
]};
skia_backend_textures
[
1
]
=
GrBackendTexture
(
/*width=*/
texture_size
.
width
(),
/*height=*/
texture_size
.
height
(),
/*mipMapped=*/
GrMipMapped
::
kNo
,
/*textureInfo=*/
uv_skia_texture_info
);
SkYUVAInfo
yuva_info
(
skia_backend_textures
[
0
].
dimensions
(),
SkYUVAInfo
::
PlaneConfig
::
kY_UV
,
SkYUVAInfo
::
Subsampling
::
k444
,
kRec601_SkYUVColorSpace
);
GrYUVABackendTextures
yuva_backend_textures
(
yuva_info
,
skia_backend_textures
,
kTopLeft_GrSurfaceOrigin
);
struct
ImageCaptures
{
fml
::
CFRef
<
CVPixelBufferRef
>
buffer
;
fml
::
CFRef
<
CVMetalTextureRef
>
y_texture
;
fml
::
CFRef
<
CVMetalTextureRef
>
uv_texture
;
};
auto
captures
=
std
::
make_unique
<
ImageCaptures
>
();
captures
->
buffer
=
std
::
move
(
pixel_buffer
);
captures
->
y_texture
=
std
::
move
(
y_metal_texture
);
captures
->
uv_texture
=
std
::
move
(
uv_metal_texture
);
SkImage
::
TextureReleaseProc
release_proc
=
[](
SkImage
::
ReleaseContext
release_context
)
{
auto
captures
=
reinterpret_cast
<
ImageCaptures
*>
(
release_context
);
delete
captures
;
};
sk_sp
<
SkImage
>
image
=
SkImage
::
MakeFromYUVATextures
(
context
,
yuva_backend_textures
,
/*imageColorSpace=*/
nullptr
,
release_proc
,
captures
.
release
());
return
image
;
}
sk_sp
<
SkImage
>
IOSExternalTextureMetal
::
WrapRGBAExternalPixelBuffer
(
fml
::
CFRef
<
CVPixelBufferRef
>
pixel_buffer
,
GrDirectContext
*
context
)
const
{
auto
texture_size
=
SkISize
::
Make
(
CVPixelBufferGetWidth
(
pixel_buffer
),
CVPixelBufferGetHeight
(
pixel_buffer
));
CVMetalTextureRef
metal_texture_raw
=
nullptr
;
auto
cv_return
=
CVMetalTextureCacheCreateTextureFromImage
(
/*allocator=*/
kCFAllocatorDefault
,
/*textureCache=*/
texture_cache_
,
/*sourceImage=*/
pixel_buffer
,
/*textureAttributes=*/
nullptr
,
/*pixelFormat=*/
MTLPixelFormatBGRA8Unorm
,
/*width=*/
texture_size
.
width
(),
/*height=*/
texture_size
.
height
(),
/*planeIndex=*/
0u
,
/*texture=*/
&
metal_texture_raw
);
if
(
cv_return
!=
kCVReturnSuccess
)
{
FML_DLOG
(
ERROR
)
<<
"Could not create Metal texture from pixel buffer: CVReturn "
<<
cv_return
;
return
nullptr
;
}
fml
::
CFRef
<
CVMetalTextureRef
>
metal_texture
(
metal_texture_raw
);
GrMtlTextureInfo
skia_texture_info
;
skia_texture_info
.
fTexture
=
sk_cf_obj
<
const
void
*>
{
[
reinterpret_cast
<
NSObject
*>
(
CVMetalTextureGetTexture
(
metal_texture
))
retain
]};
GrBackendTexture
skia_backend_texture
(
/*width=*/
texture_size
.
width
(),
/*height=*/
texture_size
.
height
(),
/*mipMapped=*/
GrMipMapped
::
kNo
,
/*textureInfo=*/
skia_texture_info
);
struct
ImageCaptures
{
fml
::
CFRef
<
CVPixelBufferRef
>
buffer
;
fml
::
CFRef
<
CVMetalTextureRef
>
texture
;
};
auto
captures
=
std
::
make_unique
<
ImageCaptures
>
();
captures
->
buffer
=
std
::
move
(
pixel_buffer
);
captures
->
texture
=
std
::
move
(
metal_texture
);
SkImage
::
TextureReleaseProc
release_proc
=
[](
SkImage
::
ReleaseContext
release_context
)
{
auto
captures
=
reinterpret_cast
<
ImageCaptures
*>
(
release_context
);
delete
captures
;
};
auto
image
=
SkImage
::
MakeFromTexture
(
context
,
skia_backend_texture
,
kTopLeft_GrSurfaceOrigin
,
kBGRA_8888_SkColorType
,
kPremul_SkAlphaType
,
/*imageColorSpace=*/
nullptr
,
release_proc
,
captures
.
release
()
);
return
image
;
[
darwin_external_texture_metal_
paint
:
canvas
bounds:
bounds
freeze:
freeze
grContext:
context
sampling:
sampling
];
}
void
IOSExternalTextureMetal
::
OnGrContextCreated
()
{
// External images in this backend have no thread affinity and are not tied to the context in any
// way. Instead, they are tied to the Metal device which is associated with the cache already and
// is consistent throughout the shell run.
[
darwin_external_texture_metal_
onGrContextCreated
];
}
void
IOSExternalTextureMetal
::
OnGrContextDestroyed
()
{
// The image must be reset because it is tied to the onscreen context. But the pixel buffer that
// created the image is still around. In case of context reacquisition, that last pixel
// buffer will be used to materialize the image in case the application fails to provide a new
// one.
external_image_
.
reset
();
CVMetalTextureCacheFlush
(
texture_cache_
,
// cache
0
// options (must be zero)
);
[
darwin_external_texture_metal_
onGrContextDestroyed
];
}
void
IOSExternalTextureMetal
::
MarkNewFrameAvailable
()
{
texture_frame_available_
=
true
;
[
darwin_external_texture_metal_
markNewFrameAvailable
]
;
}
void
IOSExternalTextureMetal
::
OnTextureUnregistered
()
{
if
([
external_texture_
respondsToSelector
:
@selector
(
onTextureUnregistered
:)])
{
[
external_texture_
onTextureUnregistered
:
external_texture_
];
}
[
darwin_external_texture_metal_
onTextureUnregistered
];
}
}
// namespace flutter
shell/platform/darwin/macos/BUILD.gn
浏览文件 @
a322e69b
...
...
@@ -115,7 +115,7 @@ source_set("flutter_framework_source") {
"FLUTTER_ENGINE_NO_PROTOTYPES",
]
cflags_objcc =
[ "-fobjc-arc" ]
cflags_objcc =
flutter_cflags_objcc_arc
libs = [
"Cocoa.framework",
...
...
@@ -161,7 +161,7 @@ executable("flutter_desktop_darwin_unittests") {
sources += [ "framework/Source/FlutterOpenGLRendererTest.mm" ]
}
cflags_objcc =
[ "-fobjc-arc" ]
cflags_objcc =
flutter_cflags_objcc_arc
ldflags = [ "-ObjC" ]
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录