Commit 5bb4a0a1 authored by Stephen McGruer's avatar Stephen McGruer Committed by Commit Bot

[PaintWorklet] Initial work to thread PaintWorkletGlobalScope

This CL introduces an alternative constructor for
PaintWorkletGlobalScope which will make it call the threaded constructor
for WorkletGlobalScope. The choice of which type to use is made in
PaintWorklet::CreateGlobalScope, based on the OffMainThreadCSSPaint
blink feature flag.

This CL should have no behavioral change when OffMainThreadCSSPaint is
not specified.

Bug: 890759
Change-Id: Ie971883e605a61e13c6dcdda7ad43487d1c840bb
Reviewed-on: https://chromium-review.googlesource.com/c/1273151
Commit-Queue: Stephen McGruer <smcgruer@chromium.org>
Reviewed-by: default avatarXida Chen <xidachen@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#604790}
parent 934a3287
......@@ -260,6 +260,7 @@ jumbo_source_set("unit_tests") {
"credentialmanager/credentials_container_test.cc",
"credentialmanager/password_credential_test.cc",
"csspaint/paint_rendering_context_2d_test.cc",
"csspaint/paint_worklet_global_scope_test.cc",
"csspaint/paint_worklet_test.cc",
"device_orientation/device_motion_event_pump_unittest.cc",
"device_orientation/device_orientation_event_pump_unittest.cc",
......
......@@ -23,7 +23,11 @@ blink_modules_sources("csspaint") {
"paint_worklet_global_scope.h",
"paint_worklet_global_scope_proxy.cc",
"paint_worklet_global_scope_proxy.h",
"paint_worklet_messaging_proxy.cc",
"paint_worklet_messaging_proxy.h",
"paint_worklet_pending_generator_registry.cc",
"paint_worklet_pending_generator_registry.h",
"paint_worklet_proxy_client.cc",
"paint_worklet_proxy_client.h",
]
}
......@@ -3,4 +3,5 @@ include_rules = [
"+third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h",
"+third_party/blink/renderer/modules/csspaint",
"+third_party/blink/renderer/modules/modules_export.h",
"+third_party/blink/renderer/modules/worklet",
]
......@@ -67,6 +67,9 @@ class MODULES_EXPORT CSSPaintDefinition final
ScriptState* GetScriptState() const { return script_state_; }
v8::Local<v8::Function> ConstructorForTesting(v8::Isolate* isolate) {
return constructor_.NewLocal(isolate);
}
v8::Local<v8::Function> PaintFunctionForTesting(v8::Isolate* isolate) {
return paint_.NewLocal(isolate);
}
......
......@@ -11,6 +11,8 @@
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/modules/csspaint/css_paint_definition.h"
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h"
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_messaging_proxy.h"
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
namespace blink {
......@@ -90,6 +92,9 @@ scoped_refptr<Image> PaintWorklet::Paint(const String& name,
const ImageResourceObserver& observer,
const FloatSize& container_size,
const CSSStyleValueVector* data) {
if (RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled())
return nullptr;
if (!document_definition_map_.Contains(name))
return nullptr;
......@@ -123,9 +128,20 @@ bool PaintWorklet::NeedsToCreateGlobalScope() {
WorkletGlobalScopeProxy* PaintWorklet::CreateGlobalScope() {
DCHECK(NeedsToCreateGlobalScope());
return new PaintWorkletGlobalScopeProxy(
To<Document>(GetExecutionContext())->GetFrame(), ModuleResponsesMap(),
pending_generator_registry_, GetNumberOfGlobalScopes() + 1);
if (!RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()) {
return new PaintWorkletGlobalScopeProxy(
To<Document>(GetExecutionContext())->GetFrame(), ModuleResponsesMap(),
pending_generator_registry_, GetNumberOfGlobalScopes() + 1);
}
PaintWorkletProxyClient* proxy_client = PaintWorkletProxyClient::Create();
WorkerClients* worker_clients = WorkerClients::Create();
ProvidePaintWorkletProxyClientTo(worker_clients, proxy_client);
PaintWorkletMessagingProxy* proxy =
new PaintWorkletMessagingProxy(GetExecutionContext());
proxy->Initialize(worker_clients, ModuleResponsesMap());
return proxy;
}
} // namespace blink
......@@ -17,10 +17,12 @@
#include "third_party/blink/renderer/core/inspector/main_thread_debugger.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h"
#include "third_party/blink/renderer/modules/csspaint/css_paint_definition.h"
#include "third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.h"
#include "third_party/blink/renderer/modules/csspaint/css_paint_worklet.h"
#include "third_party/blink/renderer/modules/csspaint/paint_worklet.h"
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding_macros.h"
namespace blink {
......@@ -93,6 +95,7 @@ PaintWorkletGlobalScope* PaintWorkletGlobalScope::Create(
WorkerReportingProxy& reporting_proxy,
PaintWorkletPendingGeneratorRegistry* pending_generator_registry,
size_t global_scope_number) {
DCHECK(!RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled());
auto* global_scope =
new PaintWorkletGlobalScope(frame, std::move(creation_params),
reporting_proxy, pending_generator_registry);
......@@ -106,6 +109,14 @@ PaintWorkletGlobalScope* PaintWorkletGlobalScope::Create(
return global_scope;
}
// static
PaintWorkletGlobalScope* PaintWorkletGlobalScope::Create(
std::unique_ptr<GlobalScopeCreationParams> creation_params,
WorkerThread* thread) {
DCHECK(RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled());
return new PaintWorkletGlobalScope(std::move(creation_params), thread);
}
PaintWorkletGlobalScope::PaintWorkletGlobalScope(
LocalFrame* frame,
std::unique_ptr<GlobalScopeCreationParams> creation_params,
......@@ -114,12 +125,26 @@ PaintWorkletGlobalScope::PaintWorkletGlobalScope(
: WorkletGlobalScope(std::move(creation_params), reporting_proxy, frame),
pending_generator_registry_(pending_generator_registry) {}
PaintWorkletGlobalScope::PaintWorkletGlobalScope(
std::unique_ptr<GlobalScopeCreationParams> creation_params,
WorkerThread* thread)
: WorkletGlobalScope(std::move(creation_params),
thread->GetWorkerReportingProxy(),
thread) {}
PaintWorkletGlobalScope::~PaintWorkletGlobalScope() = default;
void PaintWorkletGlobalScope::Dispose() {
MainThreadDebugger::Instance()->ContextWillBeDestroyed(
ScriptController()->GetScriptState());
pending_generator_registry_ = nullptr;
DCHECK(IsContextThread());
if (RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()) {
if (PaintWorkletProxyClient* proxy_client =
PaintWorkletProxyClient::From(Clients()))
proxy_client->Dispose();
} else {
MainThreadDebugger::Instance()->ContextWillBeDestroyed(
ScriptController()->GetScriptState());
pending_generator_registry_ = nullptr;
}
WorkletGlobalScope::Dispose();
}
......@@ -127,6 +152,8 @@ void PaintWorkletGlobalScope::registerPaint(
const String& name,
const ScriptValue& constructor_value,
ExceptionState& exception_state) {
RegisterWithProxyClientIfNeeded();
if (name.IsEmpty()) {
exception_state.ThrowTypeError("The empty string is not a valid name.");
return;
......@@ -185,34 +212,36 @@ void PaintWorkletGlobalScope::registerPaint(
// TODO(xidachen): the following steps should be done with a postTask when
// we move PaintWorklet off main thread.
PaintWorklet* paint_worklet =
PaintWorklet::From(*GetFrame()->GetDocument()->domWindow());
PaintWorklet::DocumentDefinitionMap& document_definition_map =
paint_worklet->GetDocumentDefinitionMap();
if (document_definition_map.Contains(name)) {
DocumentPaintDefinition* existing_document_definition =
document_definition_map.at(name);
if (existing_document_definition == kInvalidDocumentPaintDefinition)
return;
if (!existing_document_definition->RegisterAdditionalPaintDefinition(
*definition)) {
document_definition_map.Set(name, kInvalidDocumentPaintDefinition);
exception_state.ThrowDOMException(
DOMExceptionCode::kNotSupportedError,
"A class with name:'" + name +
"' was registered with a different definition.");
return;
if (!RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()) {
PaintWorklet* paint_worklet =
PaintWorklet::From(*GetFrame()->GetDocument()->domWindow());
PaintWorklet::DocumentDefinitionMap& document_definition_map =
paint_worklet->GetDocumentDefinitionMap();
if (document_definition_map.Contains(name)) {
DocumentPaintDefinition* existing_document_definition =
document_definition_map.at(name);
if (existing_document_definition == kInvalidDocumentPaintDefinition)
return;
if (!existing_document_definition->RegisterAdditionalPaintDefinition(
*definition)) {
document_definition_map.Set(name, kInvalidDocumentPaintDefinition);
exception_state.ThrowDOMException(
DOMExceptionCode::kNotSupportedError,
"A class with name:'" + name +
"' was registered with a different definition.");
return;
}
// Notify the generator ready only when register paint is called the
// second time with the same |name| (i.e. there is already a document
// definition associated with |name|
if (existing_document_definition->GetRegisteredDefinitionCount() ==
PaintWorklet::kNumGlobalScopes)
pending_generator_registry_->NotifyGeneratorReady(name);
} else {
DocumentPaintDefinition* document_definition =
new DocumentPaintDefinition(definition);
document_definition_map.Set(name, document_definition);
}
// Notify the generator ready only when register paint is called the second
// time with the same |name| (i.e. there is already a document definition
// associated with |name|
if (existing_document_definition->GetRegisteredDefinitionCount() ==
PaintWorklet::kNumGlobalScopes)
pending_generator_registry_->NotifyGeneratorReady(name);
} else {
DocumentPaintDefinition* document_definition =
new DocumentPaintDefinition(definition);
document_definition_map.Set(name, document_definition);
}
}
......@@ -222,7 +251,11 @@ CSSPaintDefinition* PaintWorkletGlobalScope::FindDefinition(
}
double PaintWorkletGlobalScope::devicePixelRatio() const {
return GetFrame()->DevicePixelRatio();
// TODO(smcgruer): Implement |devicePixelRatio| for worklet-thread bound
// PaintWorkletGlobalScope.
return RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()
? 1.0
: GetFrame()->DevicePixelRatio();
}
void PaintWorkletGlobalScope::Trace(blink::Visitor* visitor) {
......@@ -231,4 +264,15 @@ void PaintWorkletGlobalScope::Trace(blink::Visitor* visitor) {
WorkletGlobalScope::Trace(visitor);
}
void PaintWorkletGlobalScope::RegisterWithProxyClientIfNeeded() {
if (registered_ || !RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled())
return;
if (PaintWorkletProxyClient* proxy_client =
PaintWorkletProxyClient::From(Clients())) {
proxy_client->SetGlobalScope(this);
registered_ = true;
}
}
} // namespace blink
......@@ -24,12 +24,19 @@ class MODULES_EXPORT PaintWorkletGlobalScope final : public WorkletGlobalScope {
USING_GARBAGE_COLLECTED_MIXIN(PaintWorkletGlobalScope);
public:
// Creates a main-thread bound PaintWorkletGlobalScope.
static PaintWorkletGlobalScope* Create(
LocalFrame*,
std::unique_ptr<GlobalScopeCreationParams>,
WorkerReportingProxy&,
PaintWorkletPendingGeneratorRegistry*,
size_t global_scope_number);
// Creates an worklet-thread bound PaintWorkletGlobalScope.
static PaintWorkletGlobalScope* Create(
std::unique_ptr<GlobalScopeCreationParams>,
WorkerThread*);
~PaintWorkletGlobalScope() override;
void Dispose() final;
......@@ -49,13 +56,29 @@ class MODULES_EXPORT PaintWorkletGlobalScope final : public WorkletGlobalScope {
WorkerReportingProxy&,
PaintWorkletPendingGeneratorRegistry*);
PaintWorkletGlobalScope(std::unique_ptr<GlobalScopeCreationParams>,
WorkerThread*);
// Registers the global scope with a proxy client, if not already done. Only
// used for worklet-thread bound PaintWorkletGlobalScopes.
void RegisterWithProxyClientIfNeeded();
// The implementation of the "paint definition" concept:
// https://drafts.css-houdini.org/css-paint-api/#paint-definition
typedef HeapHashMap<String, TraceWrapperMember<CSSPaintDefinition>>
DefinitionMap;
DefinitionMap paint_definitions_;
Member<PaintWorkletPendingGeneratorRegistry> pending_generator_registry_;
// Only used for main-thread bound PaintWorkletGlobalScopes.
// TODO(smcgruer): Move elsewhere for worklet-thread bound
// PaintWorkletGlobalScope.
Member<PaintWorkletPendingGeneratorRegistry> pending_generator_registry_ =
nullptr;
// Tracks whether this PaintWorkletGlobalScope has been registered with a
// PaintWorkletProxyClient. Only used in worklet-thread bound
// PaintWorkletGlobalScopes.
bool registered_ = false;
};
template <>
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h"
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
#include "third_party/blink/renderer/core/inspector/worker_devtools_params.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
#include "third_party/blink/renderer/core/script/script.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
#include "third_party/blink/renderer/modules/csspaint/css_paint_definition.h"
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h"
#include "third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
namespace blink {
namespace {
class MockPaintWorkletProxyClient : public PaintWorkletProxyClient {
public:
MockPaintWorkletProxyClient()
: PaintWorkletProxyClient(), did_set_global_scope_(false) {}
void SetGlobalScope(WorkletGlobalScope*) override {
did_set_global_scope_ = true;
}
bool did_set_global_scope() { return did_set_global_scope_; }
private:
bool did_set_global_scope_;
};
} // namespace
// TODO(smcgruer): Extract a common base class between this and
// AnimationWorkletGlobalScope.
class PaintWorkletGlobalScopeTest : public PageTestBase {
public:
PaintWorkletGlobalScopeTest() = default;
void SetUp() override {
PageTestBase::SetUp(IntSize());
Document* document = &GetDocument();
document->SetURL(KURL("https://example.com/"));
document->UpdateSecurityOrigin(SecurityOrigin::Create(document->Url()));
reporting_proxy_ = std::make_unique<WorkerReportingProxy>();
}
std::unique_ptr<AnimationAndPaintWorkletThread>
CreateAnimationAndPaintWorkletThread(PaintWorkletProxyClient* proxy_client) {
std::unique_ptr<AnimationAndPaintWorkletThread> thread =
AnimationAndPaintWorkletThread::CreateForPaintWorklet(
*reporting_proxy_);
WorkerClients* clients = WorkerClients::Create();
if (proxy_client)
ProvidePaintWorkletProxyClientTo(clients, proxy_client);
Document* document = &GetDocument();
thread->Start(
std::make_unique<GlobalScopeCreationParams>(
document->Url(), ScriptType::kModule, document->UserAgent(),
Vector<CSPHeaderAndType>(), document->GetReferrerPolicy(),
document->GetSecurityOrigin(), document->IsSecureContext(),
document->GetHttpsState(), clients, document->AddressSpace(),
OriginTrialContext::GetTokens(document).get(),
base::UnguessableToken::Create(), nullptr /* worker_settings */,
kV8CacheOptionsDefault, new WorkletModuleResponsesMap),
base::nullopt, std::make_unique<WorkerDevToolsParams>(),
ParentExecutionContextTaskRunners::Create());
return thread;
}
using TestCalback = void (PaintWorkletGlobalScopeTest::*)(WorkerThread*,
WaitableEvent*);
// Create a new paint worklet and run the callback task on it. Terminate the
// worklet once the task completion is signaled.
void RunTestOnWorkletThread(TestCalback callback) {
std::unique_ptr<WorkerThread> worklet =
CreateAnimationAndPaintWorkletThread(nullptr);
WaitableEvent waitable_event;
PostCrossThreadTask(
*worklet->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
CrossThreadBind(callback, CrossThreadUnretained(this),
CrossThreadUnretained(worklet.get()),
CrossThreadUnretained(&waitable_event)));
waitable_event.Wait();
worklet->Terminate();
worklet->WaitForShutdownForTesting();
}
void RunScriptOnWorklet(String source_code,
WorkerThread* thread,
WaitableEvent* waitable_event) {
ASSERT_TRUE(thread->IsCurrentThread());
auto* global_scope = To<PaintWorkletGlobalScope>(thread->GlobalScope());
ScriptState* script_state =
global_scope->ScriptController()->GetScriptState();
ASSERT_TRUE(script_state);
v8::Isolate* isolate = script_state->GetIsolate();
ASSERT_TRUE(isolate);
ScriptState::Scope scope(script_state);
ASSERT_TRUE(EvaluateScriptModule(global_scope, source_code));
waitable_event->Signal();
}
void RunBasicParsingTestOnWorklet(WorkerThread* thread,
WaitableEvent* waitable_event) {
ASSERT_TRUE(thread->IsCurrentThread());
auto* global_scope = To<PaintWorkletGlobalScope>(thread->GlobalScope());
ScriptState* script_state =
global_scope->ScriptController()->GetScriptState();
ASSERT_TRUE(script_state);
v8::Isolate* isolate = script_state->GetIsolate();
ASSERT_TRUE(isolate);
ScriptState::Scope scope(script_state);
{
// registerPaint() with a valid class definition should define an
// animator.
String source_code =
R"JS(
registerPaint('test', class {
constructor () {}
paint (ctx, size) {}
});
)JS";
ASSERT_TRUE(EvaluateScriptModule(global_scope, source_code));
CSSPaintDefinition* definition = global_scope->FindDefinition("test");
ASSERT_TRUE(definition);
EXPECT_TRUE(definition->ConstructorForTesting(isolate)->IsFunction());
EXPECT_TRUE(definition->PaintFunctionForTesting(isolate)->IsFunction());
}
{
// registerPaint() with a null class definition should fail to define
// an painter.
String source_code = "registerPaint('null', null);";
ASSERT_FALSE(EvaluateScriptModule(global_scope, source_code));
EXPECT_FALSE(global_scope->FindDefinition("null"));
}
EXPECT_FALSE(global_scope->FindDefinition("non-existent"));
waitable_event->Signal();
}
private:
bool EvaluateScriptModule(PaintWorkletGlobalScope* global_scope,
const String& source_code) {
ScriptState* script_state =
global_scope->ScriptController()->GetScriptState();
EXPECT_TRUE(script_state);
const KURL js_url("https://example.com/worklet.js");
ScriptModule module = ScriptModule::Compile(
script_state->GetIsolate(), source_code, js_url, js_url,
ScriptFetchOptions(), kSharableCrossOrigin,
TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
EXPECT_FALSE(module.IsNull());
ScriptValue exception = module.Instantiate(script_state);
EXPECT_TRUE(exception.IsEmpty());
ScriptValue value = module.Evaluate(script_state);
return value.IsEmpty();
}
std::unique_ptr<WorkerReportingProxy> reporting_proxy_;
};
TEST_F(PaintWorkletGlobalScopeTest, BasicParsing) {
ScopedOffMainThreadCSSPaintForTest off_main_thread_css_paint(true);
RunTestOnWorkletThread(
&PaintWorkletGlobalScopeTest::RunBasicParsingTestOnWorklet);
}
} // namespace blink
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_messaging_proxy.h"
#include "third_party/blink/renderer/core/workers/threaded_worklet_object_proxy.h"
#include "third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread.h"
namespace blink {
PaintWorkletMessagingProxy::PaintWorkletMessagingProxy(
ExecutionContext* execution_context)
: ThreadedWorkletMessagingProxy(execution_context) {}
void PaintWorkletMessagingProxy::Trace(blink::Visitor* visitor) {
ThreadedWorkletMessagingProxy::Trace(visitor);
}
PaintWorkletMessagingProxy::~PaintWorkletMessagingProxy() = default;
std::unique_ptr<WorkerThread> PaintWorkletMessagingProxy::CreateWorkerThread() {
return AnimationAndPaintWorkletThread::CreateForPaintWorklet(
WorkletObjectProxy());
}
} // namespace blink
// Copyright 2018 The Chromium 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 THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_PAINT_WORKLET_MESSAGING_PROXY_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_PAINT_WORKLET_MESSAGING_PROXY_H_
#include <memory>
#include "third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.h"
namespace blink {
class ExecutionContext;
class WorkerThread;
// Acts as a proxy for worklet-thread bound PaintWorkletGlobalScopes. The logic
// to actually proxy an off thread global scope is implemented in the parent.
// The main contribution of this class is to create an appropriate worklet
// thread type as part of the the worklet initialization process.
class PaintWorkletMessagingProxy final : public ThreadedWorkletMessagingProxy {
public:
explicit PaintWorkletMessagingProxy(ExecutionContext*);
void Trace(blink::Visitor*) override;
private:
~PaintWorkletMessagingProxy() override;
std::unique_ptr<WorkerThread> CreateWorkerThread() override;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_OFF_THREAD_PAINT_WORKLET_MESSAGING_PROXY_H_
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h"
#include "third_party/blink/renderer/modules/csspaint/css_paint_definition.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
namespace blink {
const char PaintWorkletProxyClient::kSupplementName[] =
"PaintWorkletProxyClient";
// static
PaintWorkletProxyClient* PaintWorkletProxyClient::Create() {
return new PaintWorkletProxyClient;
}
PaintWorkletProxyClient::PaintWorkletProxyClient()
: state_(RunState::kUninitialized) {
DCHECK(IsMainThread());
}
void PaintWorkletProxyClient::Trace(blink::Visitor* visitor) {
Supplement<WorkerClients>::Trace(visitor);
}
void PaintWorkletProxyClient::SetGlobalScope(WorkletGlobalScope* global_scope) {
DCHECK(global_scope);
DCHECK(global_scope->IsContextThread());
if (state_ == RunState::kDisposed)
return;
DCHECK(state_ == RunState::kUninitialized);
global_scope_ = static_cast<PaintWorkletGlobalScope*>(global_scope);
state_ = RunState::kWorking;
}
void PaintWorkletProxyClient::Dispose() {
if (state_ == RunState::kWorking) {
DCHECK(global_scope_);
DCHECK(global_scope_->IsContextThread());
// At worklet scope termination break the reference cycle between
// PaintWorkletGlobalScope and PaintWorkletProxyClient.
global_scope_ = nullptr;
}
DCHECK(state_ != RunState::kDisposed);
state_ = RunState::kDisposed;
}
// static
PaintWorkletProxyClient* PaintWorkletProxyClient::From(WorkerClients* clients) {
return Supplement<WorkerClients>::From<PaintWorkletProxyClient>(clients);
}
void ProvidePaintWorkletProxyClientTo(WorkerClients* clients,
PaintWorkletProxyClient* client) {
clients->ProvideSupplement(client);
}
} // namespace blink
// Copyright 2018 The Chromium 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 THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_PAINT_WORKLET_PROXY_CLIENT_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_PAINT_WORKLET_PROXY_CLIENT_H_
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "third_party/blink/renderer/core/workers/worker_clients.h"
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h"
#include "third_party/blink/renderer/modules/modules_export.h"
namespace blink {
class WorkletGlobalScope;
// Mediates between a worklet-thread bound PaintWorkletGlobalScope and its
// associated dispatchers. A PaintWorkletProxyClient is associated with a single
// global scope and one dispatcher to the compositor thread.
//
// This is constructed on the main thread but it is used in the worklet backing
// thread.
//
// TODO(smcgruer): Add the dispatcher logic.
class MODULES_EXPORT PaintWorkletProxyClient
: public GarbageCollectedFinalized<PaintWorkletProxyClient>,
public Supplement<WorkerClients> {
USING_GARBAGE_COLLECTED_MIXIN(PaintWorkletProxyClient);
DISALLOW_COPY_AND_ASSIGN(PaintWorkletProxyClient);
public:
static const char kSupplementName[];
static PaintWorkletProxyClient* Create();
virtual ~PaintWorkletProxyClient() = default;
void Trace(blink::Visitor*) override;
virtual void SetGlobalScope(WorkletGlobalScope*);
void Dispose();
static PaintWorkletProxyClient* From(WorkerClients*);
protected:
PaintWorkletProxyClient();
private:
CrossThreadPersistent<PaintWorkletGlobalScope> global_scope_;
enum RunState { kUninitialized, kWorking, kDisposed } state_;
};
void MODULES_EXPORT ProvidePaintWorkletProxyClientTo(WorkerClients*,
PaintWorkletProxyClient*);
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_PAINT_WORKLET_PROXY_CLIENT_H_
......@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/workers/worker_backing_thread.h"
#include "third_party/blink/renderer/core/workers/worklet_thread_holder.h"
#include "third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.h"
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/web_thread_supporting_gc.h"
......@@ -29,6 +30,16 @@ AnimationAndPaintWorkletThread::CreateForAnimationWorklet(
WorkletType::ANIMATION_WORKLET, worker_reporting_proxy));
}
std::unique_ptr<AnimationAndPaintWorkletThread>
AnimationAndPaintWorkletThread::CreateForPaintWorklet(
WorkerReportingProxy& worker_reporting_proxy) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("paint-worklet"),
"AnimationAndPaintWorkletThread::CreateForPaintWorklet");
DCHECK(IsMainThread());
return base::WrapUnique(new AnimationAndPaintWorkletThread(
WorkletType::PAINT_WORKLET, worker_reporting_proxy));
}
template class WorkletThreadHolder<AnimationAndPaintWorkletThread>;
AnimationAndPaintWorkletThread::AnimationAndPaintWorkletThread(
......@@ -82,9 +93,9 @@ AnimationAndPaintWorkletThread::CreateWorkerGlobalScope(
this);
}
case WorkletType::PAINT_WORKLET:
// TODO(smcgruer): Add ability to create a PaintWorkletGlobalScope.
NOTREACHED();
return nullptr;
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("paint-worklet"),
"AnimationAndPaintWorkletThread::CreateWorkerGlobalScope");
return PaintWorkletGlobalScope::Create(std::move(creation_params), this);
};
}
......
......@@ -22,7 +22,8 @@ class MODULES_EXPORT AnimationAndPaintWorkletThread final
public:
static std::unique_ptr<AnimationAndPaintWorkletThread>
CreateForAnimationWorklet(WorkerReportingProxy&);
// TODO(smcgruer): Add ability to create a PaintWorklet version.
static std::unique_ptr<AnimationAndPaintWorkletThread> CreateForPaintWorklet(
WorkerReportingProxy&);
~AnimationAndPaintWorkletThread() override;
WorkerBackingThread& GetWorkerBackingThread() override;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment