1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
// Copyright 2016 The Chromium Authors
// 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_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_PAINT_WORKLET_H_
#include <memory>
#include "third_party/blink/renderer/core/css/css_syntax_definition.h"
#include "third_party/blink/renderer/core/workers/worklet.h"
#include "third_party/blink/renderer/modules/csspaint/document_paint_definition.h"
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.h"
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_pending_generator_registry.h"
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
namespace blink {
class CSSPaintImageGeneratorImpl;
// Manages a paint worklet:
// https://drafts.css-houdini.org/css-paint-api/#dom-css-paintworklet
class MODULES_EXPORT PaintWorklet : public Worklet,
public Supplement<LocalDOMWindow> {
public:
static const char kSupplementName[];
// At this moment, paint worklet allows at most two global scopes at any time.
static const wtf_size_t kNumGlobalScopesPerThread;
static PaintWorklet* From(LocalDOMWindow&);
explicit PaintWorklet(LocalDOMWindow&);
PaintWorklet(const PaintWorklet&) = delete;
PaintWorklet& operator=(const PaintWorklet&) = delete;
~PaintWorklet() override;
void AddPendingGenerator(const String& name, CSSPaintImageGeneratorImpl*);
// The |container_size| is without subpixel snapping.
scoped_refptr<Image> Paint(const String& name,
const ImageResourceObserver&,
const gfx::SizeF& container_size,
const GCedCSSStyleValueVector*);
int WorkletId() const { return worklet_id_; }
bool IsOffMainThread() const { return is_paint_off_thread_; }
void Trace(Visitor*) const override;
// The DocumentDefinitionMap tracks definitions registered via
// registerProperty; definitions are only considered valid once all global
// scopes have registered the same definition for the same thread.
typedef HashMap<String, std::unique_ptr<DocumentPaintDefinition>>
DocumentDefinitionMap;
DocumentDefinitionMap& GetDocumentDefinitionMap() {
return document_definition_map_;
}
// Used for main-thread CSS Paint. Registers a definition for a given painter,
// ensuring that the same CSSPaintDefinition is registered on all global
// scopes.
void RegisterCSSPaintDefinition(const String& name,
CSSPaintDefinition*,
ExceptionState&);
// Used for off-thread CSS Paint. In this mode we are not responsible for
// tracking whether a definition is valid - this method should only be called
// once all global scopes have registered the same |DocumentPaintDefinition|
// for the same |name|.
void RegisterMainThreadDocumentPaintDefinition(
const String& name,
Vector<CSSPropertyID> native_properties,
Vector<String> custom_properties,
Vector<CSSSyntaxDefinition> input_argument_types,
double alpha);
HeapVector<Member<WorkletGlobalScopeProxy>>& GetGlobalScopesForTesting() {
return proxies_;
}
void AddGlobalScopeForTesting() { proxies_.push_back(CreateGlobalScope()); }
bool NeedsToCreateGlobalScopeForTesting() {
return NeedsToCreateGlobalScope();
}
void SetProxyClientForTesting(PaintWorkletProxyClient* proxy_client) {
proxy_client_ = proxy_client;
}
void ResetIsPaintOffThreadForTesting();
protected:
// Since paint worklet has more than one global scope, we MUST override this
// function and provide our own selection logic.
wtf_size_t SelectGlobalScope() final;
wtf_size_t GetActiveGlobalScopeForTesting() { return active_global_scope_; }
private:
friend class PaintWorkletTest;
// Implements Worklet.
bool NeedsToCreateGlobalScope() final;
WorkletGlobalScopeProxy* CreateGlobalScope() final;
// This function calculates the number of paints to use before switching
// global scopes.
virtual int GetPaintsBeforeSwitching();
// This function calculates the next global scope to switch to.
virtual wtf_size_t SelectNewGlobalScope();
Member<PaintWorkletPendingGeneratorRegistry> pending_generator_registry_;
// Used for both main and off-thread CSS Paint.
// For the main thread, this map tracks the definitions created on the main
// thread, and ensures that all global scopes have the same definition.
//
// For the off thread case, both the worklet and main thread have this map.
// The worklet version is responsible for verifying that all global scopes
// have the same definition, and the main thread version relies on that.
//
// The value of an entry being nullptr means that it is an invalid definition.
DocumentDefinitionMap document_definition_map_;
// The last document paint frame a paint worklet painted on. This is used to
// tell when we begin painting on a new frame.
size_t active_frame_count_ = 0u;
// The current global scope being used for painting.
wtf_size_t active_global_scope_ = 0u;
// The number of paint calls remaining before Paint will select a new global
// scope. SelectGlobalScope resets this at the beginning of each frame.
int paints_before_switching_global_scope_;
// An atomic sequence number to ensure that it is unique for each paint
// worklet. This id is integrated in the PaintWorkletInput which will be used
// in PaintWorkletPaintDispatcher::Paint, to identify the right painter, to
// paint the image.
int worklet_id_;
// The proxy client associated with this PaintWorklet. We keep a reference in
// to ensure that all global scopes get the same proxy client.
Member<PaintWorkletProxyClient> proxy_client_;
// When running layout test, paint worklet has to be on the main thread
// because "enable-threaded-compositing" is off by default. However, some unit
// tests may be testing the functionality of the APIs when the paint worklet
// is off the main thread.
bool is_paint_off_thread_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_PAINT_WORKLET_H_
|