Remove the OpenGL backend on iOS (flutter/engine#34913)

This commit is contained in:
Zachary Anderson 2022-07-26 12:13:41 -07:00 committed by GitHub
parent 76aea382bf
commit 352bf98b3f
20 changed files with 8 additions and 875 deletions

View File

@ -1781,34 +1781,24 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_i
FILE: ../../../flutter/shell/platform/darwin/ios/framework/module.modulemap
FILE: ../../../flutter/shell/platform/darwin/ios/ios_context.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_context.mm
FILE: ../../../flutter/shell/platform/darwin/ios/ios_context_gl.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_context_gl.mm
FILE: ../../../flutter/shell/platform/darwin/ios/ios_context_metal_impeller.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_context_metal_impeller.mm
FILE: ../../../flutter/shell/platform/darwin/ios/ios_context_metal_skia.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_context_metal_skia.mm
FILE: ../../../flutter/shell/platform/darwin/ios/ios_context_software.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_context_software.mm
FILE: ../../../flutter/shell/platform/darwin/ios/ios_external_texture_gl.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_external_texture_gl.mm
FILE: ../../../flutter/shell/platform/darwin/ios/ios_external_texture_metal.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_external_texture_metal.mm
FILE: ../../../flutter/shell/platform/darwin/ios/ios_external_view_embedder.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_external_view_embedder.mm
FILE: ../../../flutter/shell/platform/darwin/ios/ios_render_target_gl.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_render_target_gl.mm
FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface.mm
FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_gl.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_gl.mm
FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_metal_impeller.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_metal_impeller.mm
FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_metal_skia.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_metal_skia.mm
FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_software.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_software.mm
FILE: ../../../flutter/shell/platform/darwin/ios/ios_switchable_gl_context.h
FILE: ../../../flutter/shell/platform/darwin/ios/ios_switchable_gl_context.mm
FILE: ../../../flutter/shell/platform/darwin/ios/platform_message_handler_ios.h
FILE: ../../../flutter/shell/platform/darwin/ios/platform_message_handler_ios.mm
FILE: ../../../flutter/shell/platform/darwin/ios/platform_message_handler_ios_test.mm

View File

@ -16,7 +16,7 @@ _flutter_framework_dir = "$root_out_dir/Flutter.framework"
shell_gpu_configuration("ios_gpu_configuration") {
enable_software = true
enable_gl = true
enable_gl = false
enable_vulkan = false
enable_metal = shell_enable_metal
}
@ -111,24 +111,14 @@ source_set("flutter_framework_source") {
"framework/Source/vsync_waiter_ios.mm",
"ios_context.h",
"ios_context.mm",
"ios_context_gl.h",
"ios_context_gl.mm",
"ios_context_software.h",
"ios_context_software.mm",
"ios_external_texture_gl.h",
"ios_external_texture_gl.mm",
"ios_external_view_embedder.h",
"ios_external_view_embedder.mm",
"ios_render_target_gl.h",
"ios_render_target_gl.mm",
"ios_surface.h",
"ios_surface.mm",
"ios_surface_gl.h",
"ios_surface_gl.mm",
"ios_surface_software.h",
"ios_surface_software.mm",
"ios_switchable_gl_context.h",
"ios_switchable_gl_context.mm",
"platform_message_handler_ios.h",
"platform_message_handler_ios.mm",
"platform_view_ios.h",
@ -185,7 +175,6 @@ source_set("flutter_framework_source") {
"AudioToolbox.framework",
"CoreMedia.framework",
"CoreVideo.framework",
"OpenGLES.framework",
"QuartzCore.framework",
"UIKit.framework",
]

View File

@ -11,9 +11,7 @@
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/shell/common/shell.h"
#import "flutter/shell/platform/darwin/ios/ios_context_gl.h"
#import "flutter/shell/platform/darwin/ios/ios_surface.h"
#import "flutter/shell/platform/darwin/ios/ios_surface_gl.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h"

View File

@ -13,7 +13,6 @@
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/common/rasterizer.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h"
#import "flutter/shell/platform/darwin/ios/ios_surface_gl.h"
#import "flutter/shell/platform/darwin/ios/ios_surface_software.h"
#include "third_party/skia/include/utils/mac/SkCGUtils.h"
@ -46,8 +45,7 @@
- (instancetype)initWithContentsScale:(CGFloat)contentsScale {
self = [self init];
if ([self.layer isKindOfClass:NSClassFromString(@"CAEAGLLayer")] ||
[self.layer isKindOfClass:NSClassFromString(@"CAMetalLayer")]) {
if ([self.layer isKindOfClass:NSClassFromString(@"CAMetalLayer")]) {
self.layer.allowsGroupOpacity = NO;
self.layer.contentsScale = contentsScale;
self.layer.rasterizationScale = contentsScale;

View File

@ -17,7 +17,6 @@
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h"
#import "flutter/shell/platform/darwin/ios/ios_surface.h"
#import "flutter/shell/platform/darwin/ios/ios_surface_gl.h"
@implementation UIView (FirstResponder)
- (BOOL)flt_hasFirstResponderInViewHierarchySubtree {

View File

@ -13,7 +13,6 @@
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/common/rasterizer.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h"
#import "flutter/shell/platform/darwin/ios/ios_surface_gl.h"
#import "flutter/shell/platform/darwin/ios/ios_surface_software.h"
#include "third_party/skia/include/utils/mac/SkCGUtils.h"
@ -54,8 +53,7 @@
}
- (void)layoutSubviews {
if ([self.layer isKindOfClass:NSClassFromString(@"CAEAGLLayer")] ||
[self.layer isKindOfClass:NSClassFromString(@"CAMetalLayer")]) {
if ([self.layer isKindOfClass:NSClassFromString(@"CAMetalLayer")]) {
CGFloat screenScale = [UIScreen mainScreen].scale;
self.layer.allowsGroupOpacity = YES;
self.layer.contentsScale = screenScale;

View File

@ -5,7 +5,6 @@
#import "flutter/shell/platform/darwin/ios/ios_context.h"
#include "flutter/fml/logging.h"
#import "flutter/shell/platform/darwin/ios/ios_context_gl.h"
#import "flutter/shell/platform/darwin/ios/ios_context_software.h"
#if SHELL_ENABLE_METAL
@ -23,8 +22,6 @@ std::unique_ptr<IOSContext> IOSContext::Create(IOSRenderingAPI api,
IOSRenderingBackend backend,
MsaaSampleCount msaa_samples) {
switch (api) {
case IOSRenderingAPI::kOpenGLES:
return std::make_unique<IOSContextGL>();
case IOSRenderingAPI::kSoftware:
return std::make_unique<IOSContextSoftware>();
#if SHELL_ENABLE_METAL

View File

@ -1,54 +0,0 @@
// 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.
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_GL_CONTEXT_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_GL_CONTEXT_H_
#include "flutter/fml/macros.h"
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/shell/common/platform_view.h"
#import "flutter/shell/platform/darwin/ios/ios_context.h"
#import "flutter/shell/platform/darwin/ios/ios_context_gl.h"
#import "flutter/shell/platform/darwin/ios/ios_render_target_gl.h"
@class CAEAGLLayer;
namespace flutter {
class IOSContextGL final : public IOSContext {
public:
IOSContextGL();
// |IOSContext|
~IOSContextGL() override;
std::unique_ptr<IOSRenderTargetGL> CreateRenderTarget(fml::scoped_nsobject<CAEAGLLayer> layer);
void SetMainContext(const sk_sp<GrDirectContext>& main_context);
// |IOSContext|
sk_sp<GrDirectContext> CreateResourceContext() override;
// |IOSContext|
std::unique_ptr<GLContextResult> MakeCurrent() override;
// |IOSContext|
std::unique_ptr<Texture> CreateExternalTexture(
int64_t texture_id,
fml::scoped_nsobject<NSObject<FlutterTexture>> texture) override;
// |IOSContext|
sk_sp<GrDirectContext> GetMainContext() const override;
private:
fml::scoped_nsobject<EAGLContext> context_;
fml::scoped_nsobject<EAGLContext> resource_context_;
sk_sp<GrDirectContext> main_context_;
FML_DISALLOW_COPY_AND_ASSIGN(IOSContextGL);
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_GL_CONTEXT_H_

View File

@ -1,73 +0,0 @@
// 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/ios/ios_context_gl.h"
#import <OpenGLES/EAGL.h>
#include "flutter/shell/common/shell_io_manager.h"
#include "flutter/shell/gpu/gpu_surface_gl_delegate.h"
#include "flutter/shell/gpu/gpu_surface_gl_skia.h"
#import "flutter/shell/platform/darwin/ios/ios_external_texture_gl.h"
namespace flutter {
IOSContextGL::IOSContextGL() : IOSContext(MsaaSampleCount::kNone) {
resource_context_.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3]);
if (resource_context_ != nullptr) {
context_.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3
sharegroup:resource_context_.get().sharegroup]);
} else {
resource_context_.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]);
context_.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2
sharegroup:resource_context_.get().sharegroup]);
}
}
IOSContextGL::~IOSContextGL() {
if (main_context_) {
main_context_->releaseResourcesAndAbandonContext();
}
}
std::unique_ptr<IOSRenderTargetGL> IOSContextGL::CreateRenderTarget(
fml::scoped_nsobject<CAEAGLLayer> layer) {
return std::make_unique<IOSRenderTargetGL>(std::move(layer), context_);
}
// |IOSContext|
sk_sp<GrDirectContext> IOSContextGL::CreateResourceContext() {
if (![EAGLContext setCurrentContext:resource_context_.get()]) {
FML_DLOG(INFO) << "Could not make resource context current on IO thread. Async texture uploads "
"will be disabled. On Simulators, this is expected.";
return nullptr;
}
return ShellIOManager::CreateCompatibleResourceLoadingContext(
GrBackend::kOpenGL_GrBackend, GPUSurfaceGLDelegate::GetDefaultPlatformGLInterface());
}
// |IOSContext|
sk_sp<GrDirectContext> IOSContextGL::GetMainContext() const {
return main_context_;
}
void IOSContextGL::SetMainContext(const sk_sp<GrDirectContext>& main_context) {
main_context_ = main_context;
}
// |IOSContext|
std::unique_ptr<GLContextResult> IOSContextGL::MakeCurrent() {
return std::make_unique<GLContextSwitch>(
std::make_unique<IOSSwitchableGLContext>(context_.get()));
}
// |IOSContext|
std::unique_ptr<Texture> IOSContextGL::CreateExternalTexture(
int64_t texture_id,
fml::scoped_nsobject<NSObject<FlutterTexture>> texture) {
return std::make_unique<IOSExternalTextureGL>(texture_id, std::move(texture), context_);
}
} // namespace flutter

View File

@ -1,76 +0,0 @@
// 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.
#ifndef FLUTTER_SHELL_PLATFORM_IOS_EXTERNAL_TEXTURE_GL_H_
#define FLUTTER_SHELL_PLATFORM_IOS_EXTERNAL_TEXTURE_GL_H_
#include "flutter/common/graphics/texture.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"
namespace flutter {
class IOSExternalTextureGL final : public Texture {
public:
IOSExternalTextureGL(int64_t textureId,
NSObject<FlutterTexture>* externalTexture,
fml::scoped_nsobject<EAGLContext> context);
// |Texture|
~IOSExternalTextureGL() override;
private:
bool new_frame_ready_ = false;
fml::scoped_nsobject<NSObject<FlutterTexture>> external_texture_;
fml::CFRef<CVOpenGLESTextureCacheRef> cache_ref_;
fml::CFRef<CVOpenGLESTextureRef> texture_ref_;
fml::CFRef<CVPixelBufferRef> buffer_ref_;
OSType pixel_format_ = 0;
fml::CFRef<CVOpenGLESTextureRef> y_texture_ref_;
fml::CFRef<CVOpenGLESTextureRef> uv_texture_ref_;
fml::scoped_nsobject<EAGLContext> context_;
// |Texture|
void Paint(SkCanvas& canvas,
const SkRect& bounds,
bool freeze,
GrDirectContext* context,
const SkSamplingOptions& sampling,
const SkPaint* paint) override;
// |Texture|
void OnGrContextCreated() override;
// |Texture|
void OnGrContextDestroyed() override;
// |Texture|
void MarkNewFrameAvailable() override;
// |Texture|
void OnTextureUnregistered() override;
void CreateTextureFromPixelBuffer();
void EnsureTextureCacheExists();
bool NeedUpdateTexture(bool freeze);
bool IsTexturesAvailable() const;
void CreateYUVTexturesFromPixelBuffer();
void CreateRGBATextureFromPixelBuffer();
sk_sp<SkImage> CreateImageFromYUVTextures(GrDirectContext* context, const SkRect& bounds);
sk_sp<SkImage> CreateImageFromRGBATexture(GrDirectContext* context, const SkRect& bounds);
FML_DISALLOW_COPY_AND_ASSIGN(IOSExternalTextureGL);
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_IOS_EXTERNAL_TEXTURE_GL_H_

View File

@ -1,201 +0,0 @@
// 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/ios/ios_external_texture_gl.h"
#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>
#import "flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h"
#include "third_party/skia/include/core/SkColorSpace.h"
#include "third_party/skia/include/core/SkSurface.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"
namespace flutter {
IOSExternalTextureGL::IOSExternalTextureGL(int64_t textureId,
NSObject<FlutterTexture>* externalTexture,
fml::scoped_nsobject<EAGLContext> context)
: Texture(textureId),
external_texture_(fml::scoped_nsobject<NSObject<FlutterTexture>>([externalTexture retain])),
context_(context) {
FML_DCHECK(external_texture_);
}
IOSExternalTextureGL::~IOSExternalTextureGL() = default;
void IOSExternalTextureGL::EnsureTextureCacheExists() {
if (!cache_ref_) {
CVOpenGLESTextureCacheRef cache;
CVReturn err =
CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, context_.get(), NULL, &cache);
if (err == noErr) {
cache_ref_.Reset(cache);
} else {
FML_LOG(WARNING) << "Failed to create GLES texture cache: " << err;
return;
}
}
}
void IOSExternalTextureGL::CreateTextureFromPixelBuffer() {
if (buffer_ref_ == nullptr) {
return;
}
if (pixel_format_ == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange ||
pixel_format_ == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) {
CreateYUVTexturesFromPixelBuffer();
} else {
CreateRGBATextureFromPixelBuffer();
}
}
void IOSExternalTextureGL::CreateRGBATextureFromPixelBuffer() {
CVOpenGLESTextureRef texture;
CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(
kCFAllocatorDefault, cache_ref_, buffer_ref_, /*textureAttributes=*/nullptr, GL_TEXTURE_2D,
GL_RGBA, static_cast<int>(CVPixelBufferGetWidth(buffer_ref_)),
static_cast<int>(CVPixelBufferGetHeight(buffer_ref_)), GL_BGRA, GL_UNSIGNED_BYTE, 0,
&texture);
if (err != noErr) {
FML_LOG(WARNING) << "Could not create texture from pixel buffer: " << err;
} else {
texture_ref_.Reset(texture);
}
}
void IOSExternalTextureGL::CreateYUVTexturesFromPixelBuffer() {
size_t width = CVPixelBufferGetWidth(buffer_ref_);
size_t height = CVPixelBufferGetHeight(buffer_ref_);
{
CVOpenGLESTextureRef yTexture;
CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(
kCFAllocatorDefault, cache_ref_, buffer_ref_, /*textureAttributes=*/nullptr, GL_TEXTURE_2D,
GL_LUMINANCE, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, &yTexture);
if (err != noErr) {
FML_DCHECK(yTexture) << "Could not create texture from pixel buffer: " << err;
} else {
y_texture_ref_.Reset(yTexture);
}
}
{
CVOpenGLESTextureRef uvTexture;
CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(
kCFAllocatorDefault, cache_ref_, buffer_ref_, /*textureAttributes=*/nullptr, GL_TEXTURE_2D,
GL_LUMINANCE_ALPHA, width / 2, height / 2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 1,
&uvTexture);
if (err != noErr) {
FML_DCHECK(uvTexture) << "Could not create texture from pixel buffer: " << err;
} else {
uv_texture_ref_.Reset(uvTexture);
}
}
}
sk_sp<SkImage> IOSExternalTextureGL::CreateImageFromRGBATexture(GrDirectContext* context,
const SkRect& bounds) {
GrGLTextureInfo textureInfo = {CVOpenGLESTextureGetTarget(texture_ref_),
CVOpenGLESTextureGetName(texture_ref_), GL_RGBA8_OES};
GrBackendTexture backendTexture(bounds.width(), bounds.height(), GrMipMapped::kNo, textureInfo);
sk_sp<SkImage> image = SkImage::MakeFromTexture(context, backendTexture, kTopLeft_GrSurfaceOrigin,
kRGBA_8888_SkColorType, kPremul_SkAlphaType,
/*imageColorSpace=*/nullptr);
return image;
}
sk_sp<SkImage> IOSExternalTextureGL::CreateImageFromYUVTextures(GrDirectContext* context,
const SkRect& bounds) {
GrBackendTexture textures[2];
GrGLTextureInfo yTextureInfo = {CVOpenGLESTextureGetTarget(y_texture_ref_),
CVOpenGLESTextureGetName(y_texture_ref_), GL_LUMINANCE8_EXT};
textures[0] = GrBackendTexture(bounds.width(), bounds.height(), GrMipMapped::kNo, yTextureInfo);
GrGLTextureInfo uvTextureInfo = {CVOpenGLESTextureGetTarget(uv_texture_ref_),
CVOpenGLESTextureGetName(uv_texture_ref_),
GL_LUMINANCE8_ALPHA8_EXT};
textures[1] = GrBackendTexture(bounds.width(), bounds.height(), GrMipMapped::kNo, uvTextureInfo);
SkYUVAInfo yuvaInfo(textures[0].dimensions(), SkYUVAInfo::PlaneConfig::kY_UV,
SkYUVAInfo::Subsampling::k444, kRec601_SkYUVColorSpace);
GrYUVABackendTextures yuvaBackendTextures(yuvaInfo, textures, kTopLeft_GrSurfaceOrigin);
sk_sp<SkImage> image = SkImage::MakeFromYUVATextures(context, yuvaBackendTextures,
/*imageColorSpace=*/nullptr);
return image;
}
bool IOSExternalTextureGL::IsTexturesAvailable() const {
return ((pixel_format_ == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange ||
pixel_format_ == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) &&
(y_texture_ref_ && uv_texture_ref_)) ||
(pixel_format_ == kCVPixelFormatType_32BGRA && texture_ref_);
}
bool IOSExternalTextureGL::NeedUpdateTexture(bool freeze) {
// Update texture if `texture_ref_` is reset to `nullptr` when GrContext
// is destroyed or new frame is ready.
return (!freeze && new_frame_ready_) || !IsTexturesAvailable();
}
void IOSExternalTextureGL::Paint(SkCanvas& canvas,
const SkRect& bounds,
bool freeze,
GrDirectContext* context,
const SkSamplingOptions& sampling,
const SkPaint* paint) {
EnsureTextureCacheExists();
if (NeedUpdateTexture(freeze)) {
auto pixelBuffer = [external_texture_.get() copyPixelBuffer];
if (pixelBuffer) {
buffer_ref_.Reset(pixelBuffer);
pixel_format_ = CVPixelBufferGetPixelFormatType(buffer_ref_);
}
CreateTextureFromPixelBuffer();
new_frame_ready_ = false;
}
if (!IsTexturesAvailable()) {
return;
}
sk_sp<SkImage> image = nullptr;
if (pixel_format_ == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange ||
pixel_format_ == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) {
image = CreateImageFromYUVTextures(context, bounds);
} else {
image = CreateImageFromRGBATexture(context, bounds);
}
FML_DCHECK(image) << "Failed to create SkImage from Texture.";
if (image) {
canvas.drawImage(image, bounds.x(), bounds.y(), sampling, paint);
}
}
void IOSExternalTextureGL::OnGrContextCreated() {
// Re-create texture from pixel buffer that was saved before
// OnGrContextDestroyed gets called.
// https://github.com/flutter/flutter/issues/30491
EnsureTextureCacheExists();
CreateTextureFromPixelBuffer();
}
void IOSExternalTextureGL::OnGrContextDestroyed() {
texture_ref_.Reset(nullptr);
cache_ref_.Reset(nullptr);
}
void IOSExternalTextureGL::MarkNewFrameAvailable() {
new_frame_ready_ = true;
}
void IOSExternalTextureGL::OnTextureUnregistered() {
if ([external_texture_ respondsToSelector:@selector(onTextureUnregistered:)]) {
[external_texture_ onTextureUnregistered:external_texture_];
}
}
} // namespace flutter

View File

@ -1,49 +0,0 @@
// 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.
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_RENDER_TARGET_GL_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_RENDER_TARGET_GL_H_
#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>
#import <QuartzCore/CAEAGLLayer.h>
#include "flutter/fml/macros.h"
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/shell/common/platform_view.h"
#import "flutter/shell/platform/darwin/ios/ios_switchable_gl_context.h"
namespace flutter {
class IOSRenderTargetGL {
public:
IOSRenderTargetGL(fml::scoped_nsobject<CAEAGLLayer> layer,
fml::scoped_nsobject<EAGLContext> context_);
~IOSRenderTargetGL();
bool IsValid() const;
bool PresentRenderBuffer() const;
intptr_t GetFramebuffer() const;
bool UpdateStorageSizeIfNecessary();
private:
fml::scoped_nsobject<CAEAGLLayer> layer_;
fml::scoped_nsobject<EAGLContext> context_;
GLuint framebuffer_ = GL_NONE;
GLuint colorbuffer_ = GL_NONE;
GLint storage_size_width_ = GL_NONE;
GLint storage_size_height_ = GL_NONE;
bool valid_ = false;
FML_DISALLOW_COPY_AND_ASSIGN(IOSRenderTargetGL);
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_RENDER_TARGET_GL_H_

View File

@ -1,140 +0,0 @@
// 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/ios/ios_render_target_gl.h"
#include <UIKit/UIKit.h>
#include "flutter/fml/trace_event.h"
#include "third_party/skia/include/gpu/GrContextOptions.h"
#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
namespace flutter {
IOSRenderTargetGL::IOSRenderTargetGL(fml::scoped_nsobject<CAEAGLLayer> layer,
fml::scoped_nsobject<EAGLContext> context)
: layer_(std::move(layer)), context_(context) {
FML_DCHECK(layer_ != nullptr);
FML_DCHECK(context_ != nullptr);
if (@available(iOS 9.0, *)) {
[layer_ setPresentsWithTransaction:YES];
}
auto context_switch = GLContextSwitch(std::make_unique<IOSSwitchableGLContext>(context_.get()));
[[maybe_unused]] bool context_current = context_switch.GetResult();
FML_DCHECK(context_current);
FML_DCHECK(glGetError() == GL_NO_ERROR);
// Generate the framebuffer
glGenFramebuffers(1, &framebuffer_);
FML_DCHECK(glGetError() == GL_NO_ERROR);
FML_DCHECK(framebuffer_ != GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_);
FML_DCHECK(glGetError() == GL_NO_ERROR);
// Setup color attachment
glGenRenderbuffers(1, &colorbuffer_);
FML_DCHECK(colorbuffer_ != GL_NONE);
glBindRenderbuffer(GL_RENDERBUFFER, colorbuffer_);
FML_DCHECK(glGetError() == GL_NO_ERROR);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer_);
FML_DCHECK(glGetError() == GL_NO_ERROR);
NSString* drawableColorFormat = kEAGLColorFormatRGBA8;
layer_.get().drawableProperties = @{
kEAGLDrawablePropertyColorFormat : drawableColorFormat,
kEAGLDrawablePropertyRetainedBacking : @(NO),
};
valid_ = true;
}
IOSRenderTargetGL::~IOSRenderTargetGL() {
auto context_switch = GLContextSwitch(std::make_unique<IOSSwitchableGLContext>(context_.get()));
FML_DCHECK(glGetError() == GL_NO_ERROR);
// Deletes on GL_NONEs are ignored
glDeleteFramebuffers(1, &framebuffer_);
glDeleteRenderbuffers(1, &colorbuffer_);
FML_DCHECK(glGetError() == GL_NO_ERROR);
}
// |IOSRenderTarget|
bool IOSRenderTargetGL::IsValid() const {
return valid_;
}
// |IOSRenderTarget|
intptr_t IOSRenderTargetGL::GetFramebuffer() const {
return framebuffer_;
}
// |IOSRenderTarget|
bool IOSRenderTargetGL::PresentRenderBuffer() const {
const GLenum discards[] = {
GL_DEPTH_ATTACHMENT,
GL_STENCIL_ATTACHMENT,
};
glDiscardFramebufferEXT(GL_FRAMEBUFFER, sizeof(discards) / sizeof(GLenum), discards);
glBindRenderbuffer(GL_RENDERBUFFER, colorbuffer_);
auto current_context = [EAGLContext currentContext];
FML_DCHECK(current_context != nullptr);
return [current_context presentRenderbuffer:GL_RENDERBUFFER];
}
// |IOSRenderTarget|
bool IOSRenderTargetGL::UpdateStorageSizeIfNecessary() {
const CGSize layer_size = [layer_.get() bounds].size;
const CGFloat contents_scale = layer_.get().contentsScale;
const GLint size_width = layer_size.width * contents_scale;
const GLint size_height = layer_size.height * contents_scale;
if (size_width == storage_size_width_ && size_height == storage_size_height_) {
// Nothing to do since the storage size is already consistent with the layer.
return true;
}
TRACE_EVENT_INSTANT0("flutter", "IOSRenderTargetGL::UpdateStorageSizeIfNecessary");
FML_DLOG(INFO) << "Updating render buffer storage size.";
FML_DCHECK(glGetError() == GL_NO_ERROR);
auto context_switch = GLContextSwitch(std::make_unique<IOSSwitchableGLContext>(context_.get()));
if (!context_switch.GetResult()) {
return false;
}
FML_DCHECK(glGetError() == GL_NO_ERROR);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_);
glBindRenderbuffer(GL_RENDERBUFFER, colorbuffer_);
FML_DCHECK(glGetError() == GL_NO_ERROR);
auto current_context = [EAGLContext currentContext];
if (![current_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer_.get()]) {
return false;
}
// Fetch the dimensions of the color buffer whose backing was just updated.
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &storage_size_width_);
FML_DCHECK(glGetError() == GL_NO_ERROR);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &storage_size_height_);
FML_DCHECK(glGetError() == GL_NO_ERROR);
FML_DCHECK(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
return true;
}
} // namespace flutter

View File

@ -4,7 +4,6 @@
#import "flutter/shell/platform/darwin/ios/ios_surface.h"
#import "flutter/shell/platform/darwin/ios/ios_surface_gl.h"
#import "flutter/shell/platform/darwin/ios/ios_surface_software.h"
#include "flutter/shell/platform/darwin/ios/rendering_api_selection.h"
@ -21,14 +20,6 @@ std::unique_ptr<IOSSurface> IOSSurface::Create(std::shared_ptr<IOSContext> conte
FML_DCHECK(layer);
FML_DCHECK(context);
if ([layer.get() isKindOfClass:[CAEAGLLayer class]]) {
return std::make_unique<IOSSurfaceGL>(
fml::scoped_nsobject<CAEAGLLayer>(
reinterpret_cast<CAEAGLLayer*>([layer.get() retain])), // EAGL layer
std::move(context) // context
);
}
#if SHELL_ENABLE_METAL
if (@available(iOS METAL_IOS_VERSION_BASELINE, *)) {
if ([layer.get() isKindOfClass:[CAMetalLayer class]]) {

View File

@ -1,60 +0,0 @@
// 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.
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_SURFACE_GL_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_SURFACE_GL_H_
#include "flutter/fml/macros.h"
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/shell/gpu/gpu_surface_gl_skia.h"
#import "flutter/shell/platform/darwin/ios/ios_context.h"
#import "flutter/shell/platform/darwin/ios/ios_render_target_gl.h"
#import "flutter/shell/platform/darwin/ios/ios_surface.h"
@class CAEAGLLayer;
namespace flutter {
class IOSSurfaceGL final : public IOSSurface, public GPUSurfaceGLDelegate {
public:
IOSSurfaceGL(fml::scoped_nsobject<CAEAGLLayer> layer, std::shared_ptr<IOSContext> context);
~IOSSurfaceGL() override;
// |IOSSurface|
bool IsValid() const override;
// |IOSSurface|
void UpdateStorageSizeIfNecessary() override;
// |IOSSurface|
std::unique_ptr<Surface> CreateGPUSurface(GrDirectContext* gr_context) override;
// |GPUSurfaceGLDelegate|
std::unique_ptr<GLContextResult> GLContextMakeCurrent() override;
// |GPUSurfaceGLDelegate|
bool GLContextClearCurrent() override;
// |GPUSurfaceGLDelegate|
bool GLContextPresent(const GLPresentInfo& present_info) override;
// |GPUSurfaceGLDelegate|
intptr_t GLContextFBO(GLFrameInfo frame_info) const override;
// |GPUSurfaceGLDelegate|
SurfaceFrame::FramebufferInfo GLContextFramebufferInfo() const override;
// |GPUSurfaceGLDelegate|
bool AllowsDrawingWhenGpuDisabled() const override;
private:
std::unique_ptr<IOSRenderTargetGL> render_target_;
FML_DISALLOW_COPY_AND_ASSIGN(IOSSurfaceGL);
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_SURFACE_GL_H_

View File

@ -1,99 +0,0 @@
// 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/ios/ios_surface_gl.h"
#include "flutter/fml/trace_event.h"
#include "flutter/shell/gpu/gpu_surface_gl_skia.h"
#import "flutter/shell/platform/darwin/ios/ios_context_gl.h"
namespace flutter {
static IOSContextGL* CastToGLContext(const std::shared_ptr<IOSContext>& context) {
return reinterpret_cast<IOSContextGL*>(context.get());
}
IOSSurfaceGL::IOSSurfaceGL(fml::scoped_nsobject<CAEAGLLayer> layer,
std::shared_ptr<IOSContext> context)
: IOSSurface(context) {
render_target_ = CastToGLContext(context)->CreateRenderTarget(std::move(layer));
}
IOSSurfaceGL::~IOSSurfaceGL() = default;
// |IOSSurface|
bool IOSSurfaceGL::IsValid() const {
return render_target_->IsValid();
}
// |IOSSurface|
void IOSSurfaceGL::UpdateStorageSizeIfNecessary() {
if (IsValid()) {
render_target_->UpdateStorageSizeIfNecessary();
}
}
// |IOSSurface|
std::unique_ptr<Surface> IOSSurfaceGL::CreateGPUSurface(GrDirectContext* gr_context) {
if (gr_context) {
return std::make_unique<GPUSurfaceGLSkia>(sk_ref_sp(gr_context), this, true);
} else {
IOSContextGL* gl_context = CastToGLContext(GetContext());
sk_sp<GrDirectContext> context = gl_context->GetMainContext();
if (!context) {
context = GPUSurfaceGLSkia::MakeGLContext(this);
gl_context->SetMainContext(context);
}
return std::make_unique<GPUSurfaceGLSkia>(context, this, true);
}
}
// |GPUSurfaceGLDelegate|
intptr_t IOSSurfaceGL::GLContextFBO(GLFrameInfo frame_info) const {
return IsValid() ? render_target_->GetFramebuffer() : GL_NONE;
}
// |GPUSurfaceGLDelegate|
SurfaceFrame::FramebufferInfo IOSSurfaceGL::GLContextFramebufferInfo() const {
SurfaceFrame::FramebufferInfo res;
// The onscreen surface wraps a GL renderbuffer, which is extremely slow to read on iOS.
// Certain filter effects, in particular BackdropFilter, require making a copy of
// the current destination. For performance, the iOS surface will specify that it
// does not support readback so that the engine compositor can implement a workaround
// such as rendering the scene to an offscreen surface or Skia saveLayer.
res.supports_readback = false;
return res;
}
// |GPUSurfaceGLDelegate|
std::unique_ptr<GLContextResult> IOSSurfaceGL::GLContextMakeCurrent() {
if (!IsValid()) {
return std::make_unique<GLContextDefaultResult>(false);
}
bool update_if_necessary = render_target_->UpdateStorageSizeIfNecessary();
if (!update_if_necessary) {
return std::make_unique<GLContextDefaultResult>(false);
}
return GetContext()->MakeCurrent();
}
// |GPUSurfaceGLDelegate|
bool IOSSurfaceGL::GLContextClearCurrent() {
// |GLContextMakeCurrent| should handle the scope of the gl context.
return true;
}
// |GPUSurfaceGLDelegate|
bool IOSSurfaceGL::GLContextPresent(const GLPresentInfo& present_info) {
TRACE_EVENT0("flutter", "IOSSurfaceGL::GLContextPresent");
return IsValid() && render_target_->PresentRenderBuffer();
}
// |GPUSurfaceGLDelegate|
bool IOSSurfaceGL::AllowsDrawingWhenGpuDisabled() const {
return false;
}
} // namespace flutter

View File

@ -1,49 +0,0 @@
// 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.
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_SWITCHABLE_GL_CONTEXT_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_SWITCHABLE_GL_CONTEXT_H_
#include "flutter/common/graphics/gl_context_switch.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/memory/thread_checker.h"
#include "flutter/fml/memory/weak_ptr.h"
@class EAGLContext;
namespace flutter {
//------------------------------------------------------------------------------
/// The iOS implementation of a |SwitchableGLContext|.
///
/// It wraps a pointer to an EAGLContext. When passed in the constructor of the |GLContextSwitch|,
/// this EAGLContext is set to current. When the |GLContextSwitch| destroys, the current context
/// will be restored to the context before setting this EAGLContext to current.
///
/// Note: An |IOSSwitchableGLContext| doesn't retain the EAGLContext. Someone else must retain the
/// pointer and outlive all the |IOSSwitchableGLContext|. This object is meant to be only owned by a
/// |GLContextSwitch| and should be destroyed when The |GLContectSwitch| destroys.
class IOSSwitchableGLContext final : public SwitchableGLContext {
public:
explicit IOSSwitchableGLContext(EAGLContext* context);
bool SetCurrent() override;
bool RemoveCurrent() override;
private:
// These pointers are managed by IOSRendererTarget/IOSContextGL or a 3rd party
// plugin that uses gl context. |IOSSwitchableGLContext| should never outlive
// those objects. Never release this pointer within this object.
EAGLContext* context_;
EAGLContext* previous_context_;
FML_DECLARE_THREAD_CHECKER(checker);
FML_DISALLOW_COPY_AND_ASSIGN(IOSSwitchableGLContext);
};
} // namespace flutter
#endif

View File

@ -1,25 +0,0 @@
// 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/ios/ios_switchable_gl_context.h"
#import <OpenGLES/EAGL.h>
namespace flutter {
IOSSwitchableGLContext::IOSSwitchableGLContext(EAGLContext* context) : context_(context){};
bool IOSSwitchableGLContext::SetCurrent() {
FML_DCHECK_CREATION_THREAD_IS_CURRENT(checker);
FML_DCHECK(context_ != nullptr);
EAGLContext* current_context = EAGLContext.currentContext;
previous_context_ = current_context;
return [EAGLContext setCurrentContext:context_];
};
bool IOSSwitchableGLContext::RemoveCurrent() {
FML_DCHECK_CREATION_THREAD_IS_CURRENT(checker);
return [EAGLContext setCurrentContext:previous_context_];
};
} // namespace flutter

View File

@ -13,7 +13,6 @@ namespace flutter {
enum class IOSRenderingAPI {
kSoftware,
kOpenGLES,
kMetal,
};

View File

@ -47,12 +47,14 @@ IOSRenderingAPI GetRenderingAPIForProcess(bool force_software) {
}
#endif // SHELL_ENABLE_METAL
// OpenGL will be emulated using software rendering by Apple on the simulator, so we use the
// Skia software rendering since it performs a little better than the emulated OpenGL.
// When Metal isn't available we use Skia software rendering since it performs
// a little better than emulated OpenGL. Also, omitting an OpenGL backend
// reduces binary footprint.
#if TARGET_OS_SIMULATOR
return IOSRenderingAPI::kSoftware;
#else
return IOSRenderingAPI::kOpenGLES;
FML_CHECK(false) << "Metal may only be unavailable on simulators";
return IOSRenderingAPI::kSoftware;
#endif // TARGET_OS_SIMULATOR
}
@ -60,8 +62,6 @@ Class GetCoreAnimationLayerClassForRenderingAPI(IOSRenderingAPI rendering_api) {
switch (rendering_api) {
case IOSRenderingAPI::kSoftware:
return [CALayer class];
case IOSRenderingAPI::kOpenGLES:
return [CAEAGLLayer class];
case IOSRenderingAPI::kMetal:
if (@available(iOS METAL_IOS_VERSION_BASELINE, *)) {
return [CAMetalLayer class];