Enable MSAA behind a command line flag for iOS (flutter/engine#33461)

This commit is contained in:
Dan Field 2022-05-18 17:07:05 -07:00 committed by GitHub
parent c1fbff0c90
commit ce9f6b2e43
14 changed files with 78 additions and 37 deletions

View File

@ -91,7 +91,7 @@ PointerDataDispatcherMaker ShellTestPlatformViewMetal::GetDispatcherMaker() {
// |PlatformView|
std::unique_ptr<Surface> ShellTestPlatformViewMetal::CreateRenderingSurface() {
return std::make_unique<GPUSurfaceMetalSkia>(this, [metal_context_->context() mainContext]);
return std::make_unique<GPUSurfaceMetalSkia>(this, [metal_context_->context() mainContext], 1);
}
// |GPUSurfaceMetalDelegate|

View File

@ -17,6 +17,7 @@ class SK_API_AVAILABLE_CA_METAL_LAYER GPUSurfaceMetalSkia : public Surface {
public:
GPUSurfaceMetalSkia(GPUSurfaceMetalDelegate* delegate,
sk_sp<GrDirectContext> context,
int msaa_samples,
bool render_to_surface = true);
// |Surface|
@ -30,6 +31,7 @@ class SK_API_AVAILABLE_CA_METAL_LAYER GPUSurfaceMetalSkia : public Surface {
const MTLRenderTargetType render_target_type_;
sk_sp<GrDirectContext> context_;
GrDirectContext* precompiled_sksl_context_ = nullptr;
int msaa_samples_ = 1;
// TODO(38466): Refactor GPU surface APIs take into account the fact that an
// external view embedder may want to render to the root surface. This is a
// hack to make avoid allocating resources for the root surface when an

View File

@ -47,11 +47,18 @@ sk_sp<SkSurface> CreateSurfaceFromMetalTexture(GrDirectContext* context,
GPUSurfaceMetalSkia::GPUSurfaceMetalSkia(GPUSurfaceMetalDelegate* delegate,
sk_sp<GrDirectContext> context,
int msaa_samples,
bool render_to_surface)
: delegate_(delegate),
render_target_type_(delegate->GetRenderTargetType()),
context_(std::move(context)),
render_to_surface_(render_to_surface) {}
msaa_samples_(msaa_samples),
render_to_surface_(render_to_surface) {
// Skia allows 0 and clamps it to 1.
FML_CHECK(msaa_samples_ == 0 || msaa_samples_ == 1 || msaa_samples_ == 2 || msaa_samples_ == 4 ||
msaa_samples_ == 8)
<< "Invalid MSAA sample count value: " << msaa_samples_;
}
GPUSurfaceMetalSkia::~GPUSurfaceMetalSkia() = default;
@ -120,20 +127,9 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalSkia::AcquireFrameFromCAMetalLayer(
return nullptr;
}
// TODO(dnfield): Enable MSAA behind a flag if the settings say to.
// https://github.com/flutter/flutter/issues/100392
// Rough outline of steps needed:
// Create memoryless texture
// auto texture = drawable.get().texture;
// MTLTextureDescriptor* desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:
// texture.pixelFormat width: texture.width height: texture.height: mipmapped: texture.mipmapped];
// desc.sampleCount = 4;
// Type should be multisample, count 4 or 8 (4 always supported)
// Give the new texture to skia in this call, using the same sampleCount value
// Resolve texture
auto surface = CreateSurfaceFromMetalTexture(context_.get(), drawable.get().texture,
kTopLeft_GrSurfaceOrigin, // origin
1, // sample count
msaa_samples_, // sample count
kBGRA_8888_SkColorType, // color type
nullptr, // colorspace
nullptr // surface properties
@ -197,8 +193,8 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalSkia::AcquireFrameFromMTLTexture(
}
sk_sp<SkSurface> surface =
CreateSurfaceFromMetalTexture(context_.get(), mtl_texture, kTopLeft_GrSurfaceOrigin, 1,
kBGRA_8888_SkColorType, nullptr, nullptr);
CreateSurfaceFromMetalTexture(context_.get(), mtl_texture, kTopLeft_GrSurfaceOrigin,
msaa_samples_, kBGRA_8888_SkColorType, nullptr, nullptr);
if (!surface) {
FML_LOG(ERROR) << "Could not create the SkSurface from the metal texture.";

View File

@ -19,6 +19,7 @@ namespace flutter {
namespace {
class FakeDelegate : public PlatformView::Delegate {
public:
void OnPlatformViewCreated(std::unique_ptr<Surface> surface) override {}
void OnPlatformViewDestroyed() override {}
void OnPlatformViewScheduleFrame() override {}
@ -47,7 +48,6 @@ class FakeDelegate : public PlatformView::Delegate {
void UpdateAssetResolverByType(std::unique_ptr<AssetResolver> updated_asset_resolver,
AssetResolver::AssetResolverType type) override {}
private:
flutter::Settings settings_;
};
@ -87,6 +87,29 @@ flutter::FakeDelegate fake_delegate;
return weak_factory->GetWeakPtr();
}
- (void)testMsaaSampleCount {
// Default should be 1.
XCTAssertEqual(platform_view->GetIosContext()->GetMsaaSampleCount(), 1);
// Verify the platform view creates a new context with updated msaa_samples.
// Need to use Metal, since this is ignored for Software/GL.
fake_delegate.settings_.msaa_samples = 4;
auto thread_task_runner = fml::MessageLoop::GetCurrent().GetTaskRunner();
flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
/*platform=*/thread_task_runner,
/*raster=*/thread_task_runner,
/*ui=*/thread_task_runner,
/*io=*/thread_task_runner);
auto msaa_4x_platform_view = std::make_unique<flutter::PlatformViewIOS>(
/*delegate=*/fake_delegate,
/*rendering_api=*/flutter::IOSRenderingAPI::kMetal,
/*platform_views_controller=*/nil,
/*task_runners=*/runners);
XCTAssertEqual(msaa_4x_platform_view->GetIosContext()->GetMsaaSampleCount(), 4);
}
- (void)testCallsNotifyLowMemory {
id project = OCMClassMock([FlutterDartProject class]);
FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"tester" project:project];

View File

@ -21,6 +21,9 @@ class Context;
namespace flutter {
// Supported MSAA sample count values for iOS.
enum class MsaaSampleCount { kNone = 1, kTwo = 2, kFour = 4, kEight = 8 };
//------------------------------------------------------------------------------
/// @brief Manages the lifetime of the on-screen and off-screen rendering
/// contexts on iOS. On-screen contexts are used by Flutter for
@ -45,10 +48,17 @@ class IOSContext {
///
/// @param[in] api A client rendering API supported by the
/// engine/platform.
/// @param[in] backend A client rendering backend supported by the
/// engine/platform.
/// @param[in] msaa_samples
/// The number of MSAA samples to use. Only supplied to
/// Skia, must be either 0, 1, 2, 4, or 8.
///
/// @return A valid context on success. `nullptr` on failure.
///
static std::unique_ptr<IOSContext> Create(IOSRenderingAPI api, IOSRenderingBackend backend);
static std::unique_ptr<IOSContext> Create(IOSRenderingAPI api,
IOSRenderingBackend backend,
MsaaSampleCount msaa_samples);
//----------------------------------------------------------------------------
/// @brief Collects the context object. This must happen on the thread on
@ -133,10 +143,13 @@ class IOSContext {
virtual std::shared_ptr<impeller::Context> GetImpellerContext() const;
int GetMsaaSampleCount() const { return static_cast<int>(msaa_samples_); }
protected:
IOSContext();
explicit IOSContext(MsaaSampleCount msaa_samples);
private:
MsaaSampleCount msaa_samples_ = MsaaSampleCount::kNone;
FML_DISALLOW_COPY_AND_ASSIGN(IOSContext);
};

View File

@ -15,11 +15,13 @@
namespace flutter {
IOSContext::IOSContext() = default;
IOSContext::IOSContext(MsaaSampleCount msaa_samples) : msaa_samples_(msaa_samples) {}
IOSContext::~IOSContext() = default;
std::unique_ptr<IOSContext> IOSContext::Create(IOSRenderingAPI api, IOSRenderingBackend backend) {
std::unique_ptr<IOSContext> IOSContext::Create(IOSRenderingAPI api,
IOSRenderingBackend backend,
MsaaSampleCount msaa_samples) {
switch (api) {
case IOSRenderingAPI::kOpenGLES:
return std::make_unique<IOSContextGL>();
@ -29,7 +31,7 @@ std::unique_ptr<IOSContext> IOSContext::Create(IOSRenderingAPI api, IOSRendering
case IOSRenderingAPI::kMetal:
switch (backend) {
case IOSRenderingBackend::kSkia:
return std::make_unique<IOSContextMetalSkia>();
return std::make_unique<IOSContextMetalSkia>(msaa_samples);
case IOSRenderingBackend::kImpeller:
return std::make_unique<IOSContextMetalImpeller>();
}

View File

@ -13,7 +13,7 @@
namespace flutter {
IOSContextGL::IOSContextGL() {
IOSContextGL::IOSContextGL() : IOSContext(MsaaSampleCount::kNone) {
resource_context_.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3]);
if (resource_context_ != nullptr) {
context_.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3

View File

@ -22,7 +22,8 @@ static std::shared_ptr<impeller::Context> CreateImpellerContext() {
return context;
}
IOSContextMetalImpeller::IOSContextMetalImpeller() : context_(CreateImpellerContext()) {}
IOSContextMetalImpeller::IOSContextMetalImpeller()
: IOSContext(MsaaSampleCount::kFour), context_(CreateImpellerContext()) {}
IOSContextMetalImpeller::~IOSContextMetalImpeller() = default;

View File

@ -18,7 +18,7 @@ namespace flutter {
class IOSContextMetalSkia final : public IOSContext {
public:
IOSContextMetalSkia();
explicit IOSContextMetalSkia(MsaaSampleCount msaa_samples);
~IOSContextMetalSkia();

View File

@ -12,7 +12,7 @@
namespace flutter {
IOSContextMetalSkia::IOSContextMetalSkia() {
IOSContextMetalSkia::IOSContextMetalSkia(MsaaSampleCount msaa_samples) : IOSContext(msaa_samples) {
darwin_context_metal_ = fml::scoped_nsobject<FlutterDarwinContextMetal>{
[[FlutterDarwinContextMetal alloc] initWithDefaultMTLDevice]};

View File

@ -3,10 +3,11 @@
// found in the LICENSE file.
#import "flutter/shell/platform/darwin/ios/ios_context_software.h"
#include "ios_context.h"
namespace flutter {
IOSContextSoftware::IOSContextSoftware() = default;
IOSContextSoftware::IOSContextSoftware() : IOSContext(MsaaSampleCount::kNone) {}
// |IOSContext|
IOSContextSoftware::~IOSContextSoftware() = default;

View File

@ -42,8 +42,9 @@ void IOSSurfaceMetalSkia::UpdateStorageSizeIfNecessary() {
// |IOSSurface|
std::unique_ptr<Surface> IOSSurfaceMetalSkia::CreateGPUSurface(GrDirectContext* context) {
FML_DCHECK(context);
return std::make_unique<GPUSurfaceMetalSkia>(this, // layer
sk_ref_sp(context) // context
return std::make_unique<GPUSurfaceMetalSkia>(this, // delegate
sk_ref_sp(context), // context
GetContext()->GetMsaaSampleCount() // sample count
);
}

View File

@ -55,13 +55,15 @@ PlatformViewIOS::PlatformViewIOS(
IOSRenderingAPI rendering_api,
const std::shared_ptr<FlutterPlatformViewsController>& platform_views_controller,
flutter::TaskRunners task_runners)
: PlatformViewIOS(delegate,
IOSContext::Create(rendering_api,
delegate.OnPlatformViewGetSettings().enable_impeller
? IOSRenderingBackend::kImpeller
: IOSRenderingBackend::kSkia),
platform_views_controller,
task_runners) {}
: PlatformViewIOS(
delegate,
IOSContext::Create(
rendering_api,
delegate.OnPlatformViewGetSettings().enable_impeller ? IOSRenderingBackend::kImpeller
: IOSRenderingBackend::kSkia,
static_cast<MsaaSampleCount>(delegate.OnPlatformViewGetSettings().msaa_samples)),
platform_views_controller,
task_runners) {}
PlatformViewIOS::~PlatformViewIOS() = default;

View File

@ -44,7 +44,7 @@ std::unique_ptr<Surface> EmbedderSurfaceMetal::CreateGPUSurface() API_AVAILABLE(
}
const bool render_to_surface = !external_view_embedder_;
auto surface = std::make_unique<GPUSurfaceMetalSkia>(this, main_context_, render_to_surface);
auto surface = std::make_unique<GPUSurfaceMetalSkia>(this, main_context_, render_to_surface, 1);
if (!surface->IsValid()) {
return nullptr;