mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Enable MSAA behind a flag for Android GL, add TODOs for other platforms (flutter/engine#32128)
This commit is contained in:
parent
840af99590
commit
f396ea98b7
@ -298,6 +298,13 @@ struct Settings {
|
||||
/// on the clock used by the Dart timeline APIs. This timestamp is used
|
||||
/// to log a timeline event that tracks the latency of engine startup.
|
||||
std::chrono::microseconds engine_start_timestamp = {};
|
||||
|
||||
/// The minimum number of samples to require in multipsampled anti-aliasing.
|
||||
///
|
||||
/// Setting this value to 0 or 1 disables MSAA.
|
||||
/// If it is not 0 or 1, it must be one of 2, 4, 8, or 16. However, if the
|
||||
/// GPU does not support the requested sampling value, MSAA will be disabled.
|
||||
uint8_t msaa_samples = 0;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -469,6 +469,28 @@ Settings SettingsFromCommandLine(const fml::CommandLine& command_line) {
|
||||
&old_gen_heap_size);
|
||||
settings.old_gen_heap_size = std::stoi(old_gen_heap_size);
|
||||
}
|
||||
|
||||
if (command_line.HasOption(FlagForSwitch(Switch::MsaaSamples))) {
|
||||
std::string msaa_samples;
|
||||
command_line.GetOptionValue(FlagForSwitch(Switch::MsaaSamples),
|
||||
&msaa_samples);
|
||||
if (msaa_samples == "0") {
|
||||
settings.msaa_samples = 0;
|
||||
} else if (msaa_samples == "1") {
|
||||
settings.msaa_samples = 1;
|
||||
} else if (msaa_samples == "2") {
|
||||
settings.msaa_samples = 2;
|
||||
} else if (msaa_samples == "4") {
|
||||
settings.msaa_samples = 4;
|
||||
} else if (msaa_samples == "8") {
|
||||
settings.msaa_samples = 8;
|
||||
} else if (msaa_samples == "16") {
|
||||
settings.msaa_samples = 16;
|
||||
} else {
|
||||
FML_DLOG(ERROR) << "Invalid value for --msaa-samples: '" << msaa_samples
|
||||
<< "' (expected 0, 1, 2, 4, 8, or 16).";
|
||||
}
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
|
||||
@ -232,6 +232,13 @@ DEF_SWITCH(LeakVM,
|
||||
"When the last shell shuts down, the shared VM is leaked by default "
|
||||
"(the leak_vm in VM settings is true). To clean up the leak VM, set "
|
||||
"this value to false.")
|
||||
DEF_SWITCH(
|
||||
MsaaSamples,
|
||||
"msaa-samples",
|
||||
"The minimum number of samples to require for multisampled anti-aliasing. "
|
||||
"Setting this value to 0 or 1 disables MSAA. If it is not 0 or 1, it must "
|
||||
"be one of 2, 4, 8, or 16. However, if the GPU does not support the "
|
||||
"requested sampling value, MSAA will be disabled.")
|
||||
DEF_SWITCHES_END
|
||||
|
||||
void PrintUsage(const std::string& executable_name);
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <initializer_list>
|
||||
|
||||
#include "flutter/common/settings.h"
|
||||
#include "flutter/fml/command_line.h"
|
||||
#include "flutter/shell/common/switches.h"
|
||||
@ -56,5 +58,23 @@ TEST(SwitchesTest, RouteParsedFlag) {
|
||||
EXPECT_TRUE(settings.route.empty());
|
||||
}
|
||||
|
||||
TEST(SwitchesTest, MsaaSamples) {
|
||||
for (int samples : {0, 1, 2, 4, 8, 16}) {
|
||||
fml::CommandLine command_line = fml::CommandLineFromInitializerList(
|
||||
{"command", ("--msaa-samples=" + std::to_string(samples)).c_str()});
|
||||
Settings settings = SettingsFromCommandLine(command_line);
|
||||
EXPECT_EQ(settings.msaa_samples, samples);
|
||||
}
|
||||
fml::CommandLine command_line =
|
||||
fml::CommandLineFromInitializerList({"command", "--msaa-samples=3"});
|
||||
Settings settings = SettingsFromCommandLine(command_line);
|
||||
EXPECT_EQ(settings.msaa_samples, 0);
|
||||
|
||||
command_line =
|
||||
fml::CommandLineFromInitializerList({"command", "--msaa-samples=foobar"});
|
||||
settings = SettingsFromCommandLine(command_line);
|
||||
EXPECT_EQ(settings.msaa_samples, 0);
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
|
||||
@ -112,6 +112,17 @@ 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
|
||||
|
||||
@ -73,7 +73,9 @@ static EGLResult<EGLContext> CreateContext(EGLDisplay display,
|
||||
return {context != EGL_NO_CONTEXT, context};
|
||||
}
|
||||
|
||||
static EGLResult<EGLConfig> ChooseEGLConfiguration(EGLDisplay display) {
|
||||
static EGLResult<EGLConfig> ChooseEGLConfiguration(EGLDisplay display,
|
||||
uint8_t msaa_samples) {
|
||||
EGLint sample_buffers = msaa_samples > 1 ? 1 : 0;
|
||||
EGLint attributes[] = {
|
||||
// clang-format off
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
@ -84,6 +86,8 @@ static EGLResult<EGLConfig> ChooseEGLConfiguration(EGLDisplay display) {
|
||||
EGL_ALPHA_SIZE, 8,
|
||||
EGL_DEPTH_SIZE, 0,
|
||||
EGL_STENCIL_SIZE, 8,
|
||||
EGL_SAMPLES, static_cast<EGLint>(msaa_samples),
|
||||
EGL_SAMPLE_BUFFERS, sample_buffers,
|
||||
EGL_NONE, // termination sentinel
|
||||
// clang-format on
|
||||
};
|
||||
@ -292,7 +296,8 @@ SkISize AndroidEGLSurface::GetSize() const {
|
||||
AndroidContextGL::AndroidContextGL(
|
||||
AndroidRenderingAPI rendering_api,
|
||||
fml::RefPtr<AndroidEnvironmentGL> environment,
|
||||
const TaskRunners& task_runners)
|
||||
const TaskRunners& task_runners,
|
||||
uint8_t msaa_samples)
|
||||
: AndroidContext(AndroidRenderingAPI::kOpenGLES),
|
||||
environment_(environment),
|
||||
config_(nullptr),
|
||||
@ -305,7 +310,8 @@ AndroidContextGL::AndroidContextGL(
|
||||
bool success = false;
|
||||
|
||||
// Choose a valid configuration.
|
||||
std::tie(success, config_) = ChooseEGLConfiguration(environment_->Display());
|
||||
std::tie(success, config_) =
|
||||
ChooseEGLConfiguration(environment_->Display(), msaa_samples);
|
||||
if (!success) {
|
||||
FML_LOG(ERROR) << "Could not choose an EGL configuration.";
|
||||
LogLastEGLError();
|
||||
|
||||
@ -98,7 +98,8 @@ class AndroidContextGL : public AndroidContext {
|
||||
public:
|
||||
AndroidContextGL(AndroidRenderingAPI rendering_api,
|
||||
fml::RefPtr<AndroidEnvironmentGL> environment,
|
||||
const TaskRunners& taskRunners);
|
||||
const TaskRunners& taskRunners,
|
||||
uint8_t msaa_samples);
|
||||
|
||||
~AndroidContextGL();
|
||||
|
||||
@ -151,6 +152,11 @@ class AndroidContextGL : public AndroidContext {
|
||||
///
|
||||
EGLContext CreateNewContext() const;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief The EGLConfig for this context.
|
||||
///
|
||||
EGLConfig Config() const { return config_; }
|
||||
|
||||
private:
|
||||
fml::RefPtr<AndroidEnvironmentGL> environment_;
|
||||
EGLConfig config_;
|
||||
|
||||
@ -86,7 +86,7 @@ TEST(AndroidContextGl, Create) {
|
||||
ThreadHost::Type::UI | ThreadHost::Type::RASTER | ThreadHost::Type::IO));
|
||||
TaskRunners task_runners = MakeTaskRunners(thread_label, thread_host);
|
||||
auto context = std::make_unique<AndroidContextGL>(
|
||||
AndroidRenderingAPI::kOpenGLES, environment, task_runners);
|
||||
AndroidRenderingAPI::kOpenGLES, environment, task_runners, 0);
|
||||
context->SetMainSkiaContext(main_context);
|
||||
EXPECT_NE(context.get(), nullptr);
|
||||
context.reset();
|
||||
@ -107,7 +107,7 @@ TEST(AndroidContextGl, CreateSingleThread) {
|
||||
TaskRunners(thread_label, platform_runner, platform_runner,
|
||||
platform_runner, platform_runner);
|
||||
auto context = std::make_unique<AndroidContextGL>(
|
||||
AndroidRenderingAPI::kOpenGLES, environment, task_runners);
|
||||
AndroidRenderingAPI::kOpenGLES, environment, task_runners, 0);
|
||||
context->SetMainSkiaContext(main_context);
|
||||
EXPECT_NE(context.get(), nullptr);
|
||||
context.reset();
|
||||
@ -126,7 +126,7 @@ TEST(AndroidSurfaceGL, CreateSnapshopSurfaceWhenOnscreenSurfaceIsNotNull) {
|
||||
ThreadHost::Type::UI | ThreadHost::Type::RASTER | ThreadHost::Type::IO));
|
||||
TaskRunners task_runners = MakeTaskRunners(thread_label, thread_host);
|
||||
auto android_context = std::make_shared<AndroidContextGL>(
|
||||
AndroidRenderingAPI::kOpenGLES, environment, task_runners);
|
||||
AndroidRenderingAPI::kOpenGLES, environment, task_runners, 0);
|
||||
auto jni = std::make_shared<MockPlatformViewAndroidJNI>();
|
||||
auto android_surface =
|
||||
std::make_unique<AndroidSurfaceGL>(android_context, jni);
|
||||
@ -154,7 +154,7 @@ TEST(AndroidSurfaceGL, CreateSnapshopSurfaceWhenOnscreenSurfaceIsNull) {
|
||||
ThreadHost thread_host(host_config);
|
||||
TaskRunners task_runners = MakeTaskRunners(thread_label, thread_host);
|
||||
auto android_context = std::make_shared<AndroidContextGL>(
|
||||
AndroidRenderingAPI::kOpenGLES, environment, task_runners);
|
||||
AndroidRenderingAPI::kOpenGLES, environment, task_runners, 0);
|
||||
auto jni = std::make_shared<MockPlatformViewAndroidJNI>();
|
||||
auto android_surface =
|
||||
std::make_unique<AndroidSurfaceGL>(android_context, jni);
|
||||
@ -162,6 +162,28 @@ TEST(AndroidSurfaceGL, CreateSnapshopSurfaceWhenOnscreenSurfaceIsNull) {
|
||||
android_surface->CreateSnapshotSurface();
|
||||
EXPECT_NE(android_surface->GetOnscreenSurface(), nullptr);
|
||||
}
|
||||
|
||||
TEST(AndroidContextGl, MSAAx4) {
|
||||
GrMockOptions main_context_options;
|
||||
sk_sp<GrDirectContext> main_context =
|
||||
GrDirectContext::MakeMock(&main_context_options);
|
||||
auto environment = fml::MakeRefCounted<AndroidEnvironmentGL>();
|
||||
std::string thread_label =
|
||||
::testing::UnitTest::GetInstance()->current_test_info()->name();
|
||||
|
||||
ThreadHost thread_host(ThreadHost::ThreadHostConfig(
|
||||
thread_label,
|
||||
ThreadHost::Type::UI | ThreadHost::Type::RASTER | ThreadHost::Type::IO));
|
||||
TaskRunners task_runners = MakeTaskRunners(thread_label, thread_host);
|
||||
auto context = std::make_unique<AndroidContextGL>(
|
||||
AndroidRenderingAPI::kOpenGLES, environment, task_runners, 4);
|
||||
context->SetMainSkiaContext(main_context);
|
||||
|
||||
EGLint sample_count;
|
||||
eglGetConfigAttrib(environment->Display(), context->Config(), EGL_SAMPLES,
|
||||
&sample_count);
|
||||
EXPECT_EQ(sample_count, 4);
|
||||
}
|
||||
} // namespace android
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
|
||||
@ -113,7 +113,8 @@ AndroidShellHolder::AndroidShellHolder(
|
||||
shell.GetTaskRunners(), // task runners
|
||||
jni_facade, // JNI interop
|
||||
shell.GetSettings()
|
||||
.enable_software_rendering // use software rendering
|
||||
.enable_software_rendering, // use software rendering
|
||||
shell.GetSettings().msaa_samples // msaa sample count
|
||||
);
|
||||
weak_platform_view = platform_view_android->GetWeakPtr();
|
||||
std::vector<std::unique_ptr<Display>> displays;
|
||||
|
||||
@ -56,6 +56,8 @@ public class FlutterShellArgs {
|
||||
public static final String ARG_OBSERVATORY_PORT = "--observatory-port=";
|
||||
public static final String ARG_KEY_DART_FLAGS = "dart-flags";
|
||||
public static final String ARG_DART_FLAGS = "--dart-flags";
|
||||
public static final String ARG_KEY_MSAA_SAMPLES = "msaa-samples";
|
||||
public static final String ARG_MSAA_SAMPLES = "--msaa-samples";
|
||||
|
||||
@NonNull
|
||||
public static FlutterShellArgs fromIntent(@NonNull Intent intent) {
|
||||
@ -116,6 +118,10 @@ public class FlutterShellArgs {
|
||||
if (intent.getBooleanExtra(ARG_KEY_VERBOSE_LOGGING, false)) {
|
||||
args.add(ARG_VERBOSE_LOGGING);
|
||||
}
|
||||
final int msaaSamples = intent.getIntExtra("msaa-samples", 0);
|
||||
if (msaaSamples > 1) {
|
||||
args.add("--msaa-samples=" + Integer.toString(msaaSamples));
|
||||
}
|
||||
|
||||
// NOTE: all flags provided with this argument are subject to filtering
|
||||
// based on a a list of allowed flags in shell/common/switches.cc. If any
|
||||
|
||||
@ -46,25 +46,28 @@ std::unique_ptr<AndroidSurface> AndroidSurfaceFactoryImpl::CreateSurface() {
|
||||
|
||||
static std::shared_ptr<flutter::AndroidContext> CreateAndroidContext(
|
||||
bool use_software_rendering,
|
||||
const flutter::TaskRunners task_runners) {
|
||||
const flutter::TaskRunners task_runners,
|
||||
uint8_t msaa_samples) {
|
||||
if (use_software_rendering) {
|
||||
return std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
|
||||
}
|
||||
return std::make_unique<AndroidContextGL>(
|
||||
AndroidRenderingAPI::kOpenGLES,
|
||||
fml::MakeRefCounted<AndroidEnvironmentGL>(), task_runners);
|
||||
fml::MakeRefCounted<AndroidEnvironmentGL>(), task_runners, msaa_samples);
|
||||
}
|
||||
|
||||
PlatformViewAndroid::PlatformViewAndroid(
|
||||
PlatformView::Delegate& delegate,
|
||||
flutter::TaskRunners task_runners,
|
||||
std::shared_ptr<PlatformViewAndroidJNI> jni_facade,
|
||||
bool use_software_rendering)
|
||||
: PlatformViewAndroid(
|
||||
delegate,
|
||||
std::move(task_runners),
|
||||
std::move(jni_facade),
|
||||
CreateAndroidContext(use_software_rendering, task_runners)) {}
|
||||
bool use_software_rendering,
|
||||
uint8_t msaa_samples)
|
||||
: PlatformViewAndroid(delegate,
|
||||
std::move(task_runners),
|
||||
std::move(jni_facade),
|
||||
CreateAndroidContext(use_software_rendering,
|
||||
task_runners,
|
||||
msaa_samples)) {}
|
||||
|
||||
PlatformViewAndroid::PlatformViewAndroid(
|
||||
PlatformView::Delegate& delegate,
|
||||
|
||||
@ -45,7 +45,8 @@ class PlatformViewAndroid final : public PlatformView {
|
||||
PlatformViewAndroid(PlatformView::Delegate& delegate,
|
||||
flutter::TaskRunners task_runners,
|
||||
std::shared_ptr<PlatformViewAndroidJNI> jni_facade,
|
||||
bool use_software_rendering);
|
||||
bool use_software_rendering,
|
||||
uint8_t msaa_samples);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Creates a new PlatformViewAndroid but using an existing
|
||||
|
||||
@ -31,4 +31,27 @@ public class FlutterShellArgsTest {
|
||||
assertTrue(argValues.contains("--dart-flags=--observe --no-hot --no-pub"));
|
||||
assertTrue(argValues.contains("--trace-skia-allowlist=skia.a,skia.b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void itHandles4xMsaaFlag() {
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("msaa-samples", 4);
|
||||
|
||||
FlutterShellArgs args = FlutterShellArgs.fromIntent(intent);
|
||||
HashSet<String> argValues = new HashSet<String>(Arrays.asList(args.toArray()));
|
||||
|
||||
assertEquals(1, argValues.size());
|
||||
assertTrue(argValues.contains("--msaa-samples=4"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void itHandles1xMsaaFlag() {
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("msaa-samples", 1);
|
||||
|
||||
FlutterShellArgs args = FlutterShellArgs.fromIntent(intent);
|
||||
HashSet<String> argValues = new HashSet<String>(Arrays.asList(args.toArray()));
|
||||
|
||||
assertEquals(0, argValues.size());
|
||||
}
|
||||
}
|
||||
|
||||
@ -718,10 +718,12 @@ static sk_sp<SkSurface> MakeSkSurfaceFromBackingStore(
|
||||
context, // context
|
||||
backend_texture, // back-end texture
|
||||
kTopLeft_GrSurfaceOrigin, // surface origin
|
||||
1, // sample count
|
||||
kBGRA_8888_SkColorType, // color type
|
||||
nullptr, // color space
|
||||
&surface_properties, // surface properties
|
||||
// TODO(dnfield): Update this when embedders support MSAA, see
|
||||
// https://github.com/flutter/flutter/issues/100392
|
||||
1, // sample count
|
||||
kBGRA_8888_SkColorType, // color type
|
||||
nullptr, // color space
|
||||
&surface_properties, // surface properties
|
||||
static_cast<SkSurface::TextureReleaseProc>(
|
||||
metal->texture.destruction_callback), // release proc
|
||||
metal->texture.user_data // release context
|
||||
|
||||
@ -75,6 +75,9 @@ bool AngleSurfaceManager::InitializeEGL(
|
||||
}
|
||||
|
||||
bool AngleSurfaceManager::Initialize() {
|
||||
// TODO(dnfield): Enable MSAA here, see similar code in android_context_gl.cc
|
||||
// Will need to plumb in argument from project bundle for sampling rate.
|
||||
// https://github.com/flutter/flutter/issues/100392
|
||||
const EGLint config_attributes[] = {EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8,
|
||||
EGL_DEPTH_SIZE, 8, EGL_STENCIL_SIZE, 8,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user