forked from firka/flutter
[Impeller] Flutter GPU: Add context override. (flutter/engine#44566)
Adds a way to inject a context override, which allows us to test the API in the Dart playground without spinning up an Engine/Shell.
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:ui' as ui;
|
||||
//import 'dart:gpu';
|
||||
import '../../lib/gpu/lib/gpu.dart' as gpu;
|
||||
|
||||
void main() {}
|
||||
|
||||
@@ -11,3 +11,9 @@ void main() {}
|
||||
void sayHi() {
|
||||
print('Hi');
|
||||
}
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
void instantiateDefaultContext() {
|
||||
// ignore: unused_local_variable
|
||||
final gpu.GpuContext context = gpu.gpuContext;
|
||||
}
|
||||
|
||||
@@ -161,6 +161,7 @@ impeller_component("renderer_dart_unittests") {
|
||||
":renderer_dart_fixtures",
|
||||
"../fixtures:shader_fixtures",
|
||||
"../playground:playground_test",
|
||||
"//flutter/lib/gpu",
|
||||
"//flutter/runtime:runtime",
|
||||
"//flutter/testing:fixture_test",
|
||||
"//flutter/testing:testing",
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "flutter/common/task_runners.h"
|
||||
#include "flutter/fml/backtrace.h"
|
||||
#include "flutter/fml/command_line.h"
|
||||
#include "flutter/lib/gpu/context.h"
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
#include "flutter/runtime/dart_isolate.h"
|
||||
#include "flutter/runtime/dart_vm_lifecycle.h"
|
||||
@@ -46,7 +47,13 @@ class RendererDartTest : public PlaygroundTest,
|
||||
assert(isolate_->get()->GetPhase() == flutter::DartIsolate::Phase::Running);
|
||||
}
|
||||
|
||||
flutter::testing::AutoIsolateShutdown* GetIsolate() { return isolate_.get(); }
|
||||
flutter::testing::AutoIsolateShutdown* GetIsolate() {
|
||||
// Sneak the context into the Flutter GPU API.
|
||||
assert(GetContext() != nullptr);
|
||||
flutter::Context::SetOverrideContext(GetContext());
|
||||
|
||||
return isolate_.get();
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<flutter::testing::AutoIsolateShutdown> CreateDartIsolate() {
|
||||
@@ -90,5 +97,19 @@ TEST_P(RendererDartTest, CanRunDartInPlaygroundFrame) {
|
||||
OpenPlaygroundHere(callback);
|
||||
}
|
||||
|
||||
TEST_P(RendererDartTest, CanInstantiateFlutterGPUContext) {
|
||||
auto isolate = GetIsolate();
|
||||
bool result = isolate->RunInIsolateScope([]() -> bool {
|
||||
if (tonic::CheckAndHandleError(::Dart_Invoke(
|
||||
Dart_RootLibrary(), tonic::ToDart("instantiateDefaultContext"), 0,
|
||||
nullptr))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
ASSERT_TRUE(result);
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace impeller
|
||||
|
||||
@@ -15,6 +15,16 @@ namespace flutter {
|
||||
|
||||
IMPLEMENT_WRAPPERTYPEINFO(gpu, Context);
|
||||
|
||||
std::shared_ptr<impeller::Context> Context::override_context_;
|
||||
|
||||
void Context::SetOverrideContext(std::shared_ptr<impeller::Context> context) {
|
||||
override_context_ = std::move(context);
|
||||
}
|
||||
|
||||
std::shared_ptr<impeller::Context> Context::GetOverrideContext() {
|
||||
return override_context_;
|
||||
}
|
||||
|
||||
Context::Context(std::shared_ptr<impeller::Context> context)
|
||||
: context_(std::move(context)) {}
|
||||
|
||||
@@ -28,23 +38,28 @@ Context::~Context() = default;
|
||||
|
||||
Dart_Handle InternalFlutterGpu_Context_InitializeDefault(Dart_Handle wrapper) {
|
||||
auto dart_state = flutter::UIDartState::Current();
|
||||
if (!dart_state->IsImpellerEnabled()) {
|
||||
return tonic::ToDart(
|
||||
"Flutter GPU requires the Impeller rendering backend to be enabled.");
|
||||
|
||||
std::shared_ptr<impeller::Context> impeller_context =
|
||||
flutter::Context::GetOverrideContext();
|
||||
|
||||
if (!impeller_context) {
|
||||
if (!dart_state->IsImpellerEnabled()) {
|
||||
return tonic::ToDart(
|
||||
"Flutter GPU requires the Impeller rendering backend to be enabled.");
|
||||
}
|
||||
|
||||
// Grab the Impeller context from the IO manager.
|
||||
std::promise<std::shared_ptr<impeller::Context>> context_promise;
|
||||
auto impeller_context_future = context_promise.get_future();
|
||||
dart_state->GetTaskRunners().GetIOTaskRunner()->PostTask(
|
||||
fml::MakeCopyable([promise = std::move(context_promise),
|
||||
io_manager = dart_state->GetIOManager()]() mutable {
|
||||
promise.set_value(io_manager ? io_manager->GetImpellerContext()
|
||||
: nullptr);
|
||||
}));
|
||||
impeller_context = impeller_context_future.get();
|
||||
}
|
||||
|
||||
// Grab the Impeller context from the IO manager.
|
||||
|
||||
std::promise<std::shared_ptr<impeller::Context>> context_promise;
|
||||
auto impeller_context_future = context_promise.get_future();
|
||||
dart_state->GetTaskRunners().GetIOTaskRunner()->PostTask(
|
||||
fml::MakeCopyable([promise = std::move(context_promise),
|
||||
io_manager = dart_state->GetIOManager()]() mutable {
|
||||
promise.set_value(io_manager ? io_manager->GetImpellerContext()
|
||||
: nullptr);
|
||||
}));
|
||||
|
||||
auto impeller_context = impeller_context_future.get();
|
||||
if (!impeller_context) {
|
||||
return tonic::ToDart("Unable to retrieve the Impeller context.");
|
||||
}
|
||||
|
||||
@@ -16,9 +16,19 @@ class Context : public RefCountedDartWrappable<Context> {
|
||||
FML_FRIEND_MAKE_REF_COUNTED(Context);
|
||||
|
||||
public:
|
||||
static void SetOverrideContext(std::shared_ptr<impeller::Context> context);
|
||||
|
||||
static std::shared_ptr<impeller::Context> GetOverrideContext();
|
||||
|
||||
explicit Context(std::shared_ptr<impeller::Context> context);
|
||||
~Context() override;
|
||||
|
||||
protected:
|
||||
/// An Impeller context that takes precedent over the IO state context when
|
||||
/// set. This is used to inject the context when running with the Impeller
|
||||
/// playground, which doesn't instantiate an Engine instance.
|
||||
static std::shared_ptr<impeller::Context> override_context_;
|
||||
|
||||
private:
|
||||
std::shared_ptr<impeller::Context> context_;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user