summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/graphics
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-13 16:23:34 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-14 10:37:21 +0000
commit38a9a29f4f9436cace7f0e7abf9c586057df8a4e (patch)
treec4e8c458dc595bc0ddb435708fa2229edfd00bd4 /chromium/third_party/blink/renderer/platform/graphics
parente684a3455bcc29a6e3e66a004e352dea4e1141e7 (diff)
downloadqtwebengine-chromium-38a9a29f4f9436cace7f0e7abf9c586057df8a4e.tar.gz
BASELINE: Update Chromium to 73.0.3683.37
Change-Id: I08c9af2948b645f671e5d933aca1f7a90ea372f2 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/graphics')
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/OWNERS8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc223
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h49
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc433
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/bitmap_image_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.cc24
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc31
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc163
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/README.md2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc119
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h29
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc199
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc86
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h34
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_client.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_client.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/draw_looper_builder.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc21
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc86
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h33
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc75
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_context.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc119
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h67
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_layer_client.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc44
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image.cc32
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_pattern.cc54
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_pattern.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/intercepting_canvas.h40
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/link_highlight.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/logging_canvas.cc156
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/logging_canvas.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc30
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/main_thread_mutator_client.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/main_thread_mutator_client.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/mutator_client.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/README.md28
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.h18
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect_test.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item.h41
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc40
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h16
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item_test.cc25
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc38
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc29
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_property_node.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator_test.cc43
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/path.cc20
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/path.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/pattern.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/pattern.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/platform_paint_worklet_input.h36
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc31
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.h30
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils_test.cc44
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/texture_holder.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc516
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.h110
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc343
111 files changed, 2248 insertions, 1741 deletions
diff --git a/chromium/third_party/blink/renderer/platform/graphics/DEPS b/chromium/third_party/blink/renderer/platform/graphics/DEPS
index 4a56a8d8607..e3412554492 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/DEPS
+++ b/chromium/third_party/blink/renderer/platform/graphics/DEPS
@@ -8,6 +8,7 @@ include_rules = [
# Dependencies.
"+base/threading/sequenced_task_runner_handle.h",
"+base/threading/thread_restrictions.h",
+ "+base/barrier_closure.h",
"+cc",
"+components/viz/client",
"+components/viz/common",
@@ -21,6 +22,7 @@ include_rules = [
"+gpu/ipc/common/mailbox.mojom-blink.h",
"+media/base/media_switches.h",
"+media/base/video_frame.h",
+ "+media/base/video_types.h",
"+media/renderers/video_resource_updater.h",
"+services/viz/public/interfaces",
"+services/ws/public/cpp/gpu/context_provider_command_buffer.h",
diff --git a/chromium/third_party/blink/renderer/platform/graphics/OWNERS b/chromium/third_party/blink/renderer/platform/graphics/OWNERS
index 78c0ada3f1e..28d1c1091e5 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/graphics/OWNERS
@@ -19,3 +19,11 @@ mcasas@chromium.org
# TEAM: paint-dev@chromium.org
# COMPONENT: Blink>Paint
+
+# Video SurfaceLayer functionality.
+per-file video_frame*=file://media/OWNERS
+per-file video_frame*=mlamouri@chromium.org
+per-file video_frame*=lethalantidote@chromium.org
+per-file surface_layer_bridge*=file://media/OWNERS
+per-file surface_layer_bridge*=mlamouri@chromium.org
+per-file surface_layer_bridge*=lethalantidote@chromium.org
diff --git a/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc b/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
index 3214da58c82..851be76f139 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
@@ -289,9 +289,5 @@ bool AcceleratedStaticBitmapImage::CurrentFrameKnownToBeOpaque() {
return texture_holder_->CurrentFrameKnownToBeOpaque();
}
-void AcceleratedStaticBitmapImage::Abandon() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- texture_holder_->Abandon();
-}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h b/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h
index fa769532993..7fc90d2a08f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h
@@ -88,8 +88,6 @@ class PLATFORM_EXPORT AcceleratedStaticBitmapImage final
PaintImage PaintImageForCurrentFrame() override;
- void Abandon() final;
-
TextureHolder* TextureHolderForTesting() { return texture_holder_.get(); }
private:
diff --git a/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator.h b/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator.h
index a8d19eda503..a35b7834192 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator.h
@@ -15,7 +15,7 @@ class PLATFORM_EXPORT AnimationWorkletMutator : public GarbageCollectedMixin {
public:
virtual ~AnimationWorkletMutator() = default;
- virtual int GetScopeId() const = 0;
+ virtual int GetWorkletId() const = 0;
// Runs the animation frame callback.
virtual std::unique_ptr<AnimationWorkletOutput> Mutate(
std::unique_ptr<AnimationWorkletInput>) = 0;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher.h b/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher.h
index 441c38143e5..a7db4f11508 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher.h
@@ -15,7 +15,11 @@ class PLATFORM_EXPORT AnimationWorkletMutatorDispatcher {
virtual ~AnimationWorkletMutatorDispatcher() = default;
// Run the animation frame callbacks from all connected AnimationWorklets.
- virtual void Mutate(std::unique_ptr<AnimationWorkletDispatcherInput>) = 0;
+ virtual void MutateSynchronously(
+ std::unique_ptr<AnimationWorkletDispatcherInput>) = 0;
+ virtual void MutateAsynchronously(
+ std::unique_ptr<AnimationWorkletDispatcherInput>) = 0;
+
// Returns true if Mutate may do something if called 'now'.
virtual bool HasMutators() = 0;
};
diff --git a/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc b/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc
index 5fb4c57c500..a76626e1f0c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h"
+
+#include "base/barrier_closure.h"
#include "base/metrics/histogram_macros.h"
#include "base/timer/elapsed_timer.h"
#include "third_party/blink/public/platform/platform.h"
@@ -17,10 +19,39 @@
namespace blink {
+namespace {
+
+int next_async_mutation_id = 0;
+int GetNextAsyncMutationId() {
+ return next_async_mutation_id++;
+}
+
+} // end namespace
+
+// Wrap output vector in a thread safe and ref-counted object since it is
+// accessed from animation worklet threads and its lifetime must be guaranteed
+// to outlive the mutation update cycle.
+class AnimationWorkletMutatorDispatcherImpl::OutputVectorRef
+ : public ThreadSafeRefCounted<OutputVectorRef> {
+ public:
+ static scoped_refptr<OutputVectorRef> Create() {
+ return base::AdoptRef(new OutputVectorRef());
+ }
+ Vector<std::unique_ptr<AnimationWorkletDispatcherOutput>>& get() {
+ return vector_;
+ }
+
+ private:
+ OutputVectorRef() = default;
+ Vector<std::unique_ptr<AnimationWorkletDispatcherOutput>> vector_;
+};
+
AnimationWorkletMutatorDispatcherImpl::AnimationWorkletMutatorDispatcherImpl(
bool main_thread_task_runner)
- : client_(nullptr), weak_factory_(this) {
- // By default layout tests run without threaded compositing. See
+ : client_(nullptr),
+ outputs_(OutputVectorRef::Create()),
+ weak_factory_(this) {
+ // By default web tests run without threaded compositing. See
// https://crbug.com/770028 For these situations we run on the Main thread.
host_queue_ = main_thread_task_runner || !Thread::CompositorThread()
? Thread::MainThread()->GetTaskRunner()
@@ -62,63 +93,85 @@ AnimationWorkletMutatorDispatcherImpl::CreateMainThreadClient(
return CreateClient<MainThreadMutatorClient>(weak_interface, queue, true);
}
-void AnimationWorkletMutatorDispatcherImpl::Mutate(
+void AnimationWorkletMutatorDispatcherImpl::MutateSynchronously(
std::unique_ptr<AnimationWorkletDispatcherInput> mutator_input) {
TRACE_EVENT0("cc", "AnimationWorkletMutatorDispatcherImpl::mutate");
- if (mutator_map_.IsEmpty())
+ if (mutator_map_.IsEmpty() || !mutator_input)
return;
base::ElapsedTimer timer;
DCHECK(client_);
+ DCHECK(host_queue_->BelongsToCurrentThread());
+ DCHECK(mutator_input_map_.IsEmpty());
+ DCHECK(outputs_->get().IsEmpty());
- Vector<std::unique_ptr<AnimationWorkletDispatcherOutput>> outputs(
- mutator_map_.size());
- Vector<WaitableEvent> done_events(mutator_map_.size());
+ mutator_input_map_ = CreateInputMap(*mutator_input);
+ if (mutator_input_map_.IsEmpty())
+ return;
- int index = 0;
- for (auto& pair : mutator_map_) {
- AnimationWorkletMutator* mutator = pair.key;
- scoped_refptr<base::SingleThreadTaskRunner> worklet_queue = pair.value;
+ WaitableEvent event;
+ WTF::CrossThreadClosure on_done = CrossThreadBind(
+ &WaitableEvent::Signal, WTF::CrossThreadUnretained(&event));
+ RequestMutations(std::move(on_done));
+ event.Wait();
- std::unique_ptr<AnimationWorkletInput> input =
- mutator_input->TakeWorkletState(mutator->GetScopeId());
+ ApplyMutationsOnHostThread();
- DCHECK(!worklet_queue->BelongsToCurrentThread());
- std::unique_ptr<AutoSignal> done =
- std::make_unique<AutoSignal>(&done_events[index]);
- std::unique_ptr<AnimationWorkletDispatcherOutput>& output = outputs[index];
+ UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
+ "Animation.AnimationWorklet.Dispatcher.SynchronousMutateDuration",
+ timer.Elapsed(), base::TimeDelta::FromMicroseconds(1),
+ base::TimeDelta::FromMilliseconds(100), 50);
+}
- if (input) {
- PostCrossThreadTask(
- *worklet_queue, FROM_HERE,
- CrossThreadBind(
- [](AnimationWorkletMutator* mutator,
- std::unique_ptr<AnimationWorkletInput> input,
- std::unique_ptr<AutoSignal> completion,
- std::unique_ptr<AnimationWorkletDispatcherOutput>* output) {
- *output = mutator->Mutate(std::move(input));
- },
- WrapCrossThreadWeakPersistent(mutator),
- WTF::Passed(std::move(input)), WTF::Passed(std::move(done)),
- CrossThreadUnretained(&output)));
- }
- index++;
+void AnimationWorkletMutatorDispatcherImpl::MutateAsynchronously(
+ std::unique_ptr<AnimationWorkletDispatcherInput> mutator_input) {
+ if (mutator_map_.IsEmpty() || !mutator_input)
+ return;
+ DCHECK(client_);
+ DCHECK(host_queue_->BelongsToCurrentThread());
+ if (!mutator_input_map_.IsEmpty()) {
+ // Still running mutations from a previous frame. Skip this frame to avoid
+ // lagging behind.
+ // TODO(kevers): Consider queuing pending mutation cycle. A pending tree
+ // mutation should likely be queued an active tree mutation cycle is still
+ // running.
+ return;
}
- for (WaitableEvent& event : done_events) {
- event.Wait();
- }
+ mutator_input_map_ = CreateInputMap(*mutator_input);
+ if (mutator_input_map_.IsEmpty())
+ return;
- for (auto& output : outputs) {
- // Animator that has no input does not produce any output.
- if (!output)
- continue;
- client_->SetMutationUpdate(std::move(output));
- }
+ int next_async_mutation_id = GetNextAsyncMutationId();
+ TRACE_EVENT_ASYNC_BEGIN0("cc",
+ "AnimationWorkletMutatorDispatcherImpl::MutateAsync",
+ next_async_mutation_id);
- UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
- "Animation.AnimationWorklet.Dispatcher.SynchronousMutateDuration",
- timer.Elapsed(), base::TimeDelta::FromMicroseconds(1),
- base::TimeDelta::FromMilliseconds(100), 50);
+ WTF::CrossThreadClosure on_done = CrossThreadBind(
+ [](scoped_refptr<base::SingleThreadTaskRunner> host_queue,
+ base::WeakPtr<AnimationWorkletMutatorDispatcherImpl> dispatcher,
+ int next_async_mutation_id) {
+ PostCrossThreadTask(
+ *host_queue, FROM_HERE,
+ CrossThreadBind(
+ &AnimationWorkletMutatorDispatcherImpl::AsyncMutationsDone,
+ dispatcher, next_async_mutation_id));
+ },
+ host_queue_, weak_factory_.GetWeakPtr(), next_async_mutation_id);
+
+ client_->NotifyAnimationsPending();
+ RequestMutations(std::move(on_done));
+}
+
+void AnimationWorkletMutatorDispatcherImpl::AsyncMutationsDone(
+ int async_mutation_id) {
+ DCHECK(client_);
+ DCHECK(host_queue_->BelongsToCurrentThread());
+ ApplyMutationsOnHostThread();
+ client_->NotifyAnimationsReady();
+ TRACE_EVENT_ASYNC_END0("cc",
+ "AnimationWorkletMutatorDispatcherImpl::MutateAsync",
+ async_mutation_id);
+ // TODO(kevers): Add UMA metric to track the asynchronous mutate duration.
}
void AnimationWorkletMutatorDispatcherImpl::RegisterAnimationWorkletMutator(
@@ -145,18 +198,86 @@ void AnimationWorkletMutatorDispatcherImpl::UnregisterAnimationWorkletMutator(
mutator_map_.erase(mutator);
}
+void AnimationWorkletMutatorDispatcherImpl::SynchronizeAnimatorName(
+ const String& animator_name) {
+ client_->SynchronizeAnimatorName(animator_name);
+}
+
bool AnimationWorkletMutatorDispatcherImpl::HasMutators() {
return !mutator_map_.IsEmpty();
}
-AnimationWorkletMutatorDispatcherImpl::AutoSignal::AutoSignal(
- WaitableEvent* event)
- : event_(event) {
- DCHECK(event);
+AnimationWorkletMutatorDispatcherImpl::InputMap
+AnimationWorkletMutatorDispatcherImpl::CreateInputMap(
+ AnimationWorkletDispatcherInput& mutator_input) const {
+ InputMap input_map;
+ for (const auto& pair : mutator_map_) {
+ AnimationWorkletMutator* mutator = pair.key;
+ const int worklet_id = mutator->GetWorkletId();
+ std::unique_ptr<AnimationWorkletInput> input =
+ mutator_input.TakeWorkletState(worklet_id);
+ if (input) {
+ input_map.insert(worklet_id, std::move(input));
+ }
+ }
+ return input_map;
+}
+
+void AnimationWorkletMutatorDispatcherImpl::RequestMutations(
+ WTF::CrossThreadClosure done_callback) {
+ DCHECK(client_);
+ DCHECK(outputs_->get().IsEmpty());
+
+ int num_requests = mutator_map_.size();
+ int next_request_index = 0;
+ outputs_->get().Grow(num_requests);
+ base::RepeatingClosure on_mutator_done = base::BarrierClosure(
+ num_requests, ConvertToBaseCallback(std::move(done_callback)));
+
+ for (const auto& pair : mutator_map_) {
+ AnimationWorkletMutator* mutator = pair.key;
+ scoped_refptr<base::SingleThreadTaskRunner> worklet_queue = pair.value;
+ int worklet_id = mutator->GetWorkletId();
+ DCHECK(!worklet_queue->BelongsToCurrentThread());
+ auto it = mutator_input_map_.find(worklet_id);
+ if (it == mutator_input_map_.end()) {
+ // No input to process.
+ on_mutator_done.Run();
+ continue;
+ }
+ PostCrossThreadTask(
+ *worklet_queue, FROM_HERE,
+ CrossThreadBind(
+ [](AnimationWorkletMutator* mutator,
+ std::unique_ptr<AnimationWorkletInput> input,
+ scoped_refptr<OutputVectorRef> outputs, int index,
+ WTF::CrossThreadClosure on_mutator_done) {
+ std::unique_ptr<AnimationWorkletOutput> output =
+ mutator ? mutator->Mutate(std::move(input)) : nullptr;
+ outputs->get()[index] = std::move(output);
+ on_mutator_done.Run();
+ },
+ // The mutator is created and destroyed on the worklet thread.
+ WrapCrossThreadWeakPersistent(mutator),
+ // The worklet input is not required after the Mutate call.
+ WTF::Passed(std::move(it->value)),
+ // The vector of outputs is wrapped in a scoped_refptr initialized
+ // on the host thread. It can outlive the dispatcher during shutdown
+ // of a process with a running animation.
+ outputs_, next_request_index++,
+ WTF::Passed(WTF::CrossThreadClosure(on_mutator_done))));
+ }
}
-AnimationWorkletMutatorDispatcherImpl::AutoSignal::~AutoSignal() {
- event_->Signal();
+void AnimationWorkletMutatorDispatcherImpl::ApplyMutationsOnHostThread() {
+ DCHECK(client_);
+ DCHECK(host_queue_->BelongsToCurrentThread());
+ for (auto& output : outputs_->get()) {
+ if (output)
+ client_->SetMutationUpdate(std::move(output));
+ }
+ mutator_input_map_.clear();
+ outputs_->get().clear();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h b/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h
index 27509cdea3e..4aa67917413 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h
@@ -16,13 +16,14 @@
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/heap/visitor.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
+#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
namespace blink {
class CompositorMutatorClient;
class MainThreadMutatorClient;
-class WaitableEvent;
// Fans out requests to all of the registered AnimationWorkletMutators which can
// then run worklet animations to produce mutation updates. Requests for
@@ -47,7 +48,12 @@ class PLATFORM_EXPORT AnimationWorkletMutatorDispatcherImpl final
~AnimationWorkletMutatorDispatcherImpl() override;
// AnimationWorkletMutatorDispatcher implementation.
- void Mutate(std::unique_ptr<AnimationWorkletDispatcherInput>) override;
+ void MutateSynchronously(
+ std::unique_ptr<AnimationWorkletDispatcherInput>) override;
+
+ void MutateAsynchronously(
+ std::unique_ptr<AnimationWorkletDispatcherInput>) override;
+
// TODO(majidvp): Remove when timeline inputs are known.
bool HasMutators() override;
@@ -62,21 +68,29 @@ class PLATFORM_EXPORT AnimationWorkletMutatorDispatcherImpl final
void SetClient(MutatorClient* client) { client_ = client; }
+ void SynchronizeAnimatorName(const String& animator_name);
+
+ MutatorClient* client() { return client_; }
+
private:
+ class OutputVectorRef;
+
+ using InputMap = HashMap<int, std::unique_ptr<AnimationWorkletInput>>;
+
using AnimationWorkletMutatorToTaskRunnerMap =
HashMap<CrossThreadPersistent<AnimationWorkletMutator>,
scoped_refptr<base::SingleThreadTaskRunner>>;
- class AutoSignal {
- public:
- explicit AutoSignal(WaitableEvent*);
- ~AutoSignal();
+ InputMap CreateInputMap(AnimationWorkletDispatcherInput& mutator_input) const;
- private:
- WaitableEvent* event_;
+ // Dispatches mutation update requests. The callback is triggered once
+ // all mutation updates have been computed on the animation worklet thread
+ // associated with the last mutation to complete.
+ void RequestMutations(WTF::CrossThreadClosure done_callback);
- DISALLOW_COPY_AND_ASSIGN(AutoSignal);
- };
+ void AsyncMutationsDone(int async_mutation_id);
+
+ void ApplyMutationsOnHostThread();
// The AnimationWorkletProxyClients are also owned by the WorkerClients
// dictionary.
@@ -98,6 +112,21 @@ class PLATFORM_EXPORT AnimationWorkletMutatorDispatcherImpl final
// valid as long as this class exists.
MutatorClient* client_;
+ // Map of mutator scope IDs to mutator input. The Mutate methods safeguards
+ // against concurrent calls (important once async mutations are introduced) by
+ // checking that the map has been reset on entry. For this reason, it is
+ // important to reset the map at the end of the mutation cycle.
+ InputMap mutator_input_map_;
+
+ // Reference to a vector for collecting mutation output. The vector is
+ // accessed across threads, thus it must be guaranteed to persist until the
+ // last mutation update is complete, and updates must be done in a thread-safe
+ // manner. The Mutate method guards against concurrent calls (important once
+ // async mutations are introduced) by checking that the output vector is
+ // empty. For this reason, it is important to clear the output at the end of
+ // the mutation cycle.
+ scoped_refptr<OutputVectorRef> outputs_;
+
base::WeakPtrFactory<AnimationWorkletMutatorDispatcherImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(AnimationWorkletMutatorDispatcherImpl);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc b/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc
index 383fe843619..87b8dcd769c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc
@@ -9,18 +9,24 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_thread_type.h"
+#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/graphics/animation_worklet_mutator.h"
#include "third_party/blink/renderer/platform/graphics/compositor_mutator_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
+#include "third_party/blink/renderer/platform/waitable_event.h"
#include <memory>
using ::testing::_;
+using ::testing::AtLeast;
using ::testing::Mock;
-using ::testing::StrictMock;
using ::testing::Return;
+using ::testing::Sequence;
+using ::testing::StrictMock;
using ::testing::Truly;
// This test uses actual threads since mutator logic requires it. This means we
@@ -52,7 +58,7 @@ class MockAnimationWorkletMutator
return std::unique_ptr<AnimationWorkletOutput>(MutateRef(*input));
}
- MOCK_CONST_METHOD0(GetScopeId, int());
+ MOCK_CONST_METHOD0(GetWorkletId, int());
MOCK_METHOD1(MutateRef,
AnimationWorkletOutput*(const AnimationWorkletInput&));
@@ -63,7 +69,7 @@ class MockCompositorMutatorClient : public CompositorMutatorClient {
public:
MockCompositorMutatorClient(
std::unique_ptr<AnimationWorkletMutatorDispatcherImpl> mutator)
- : CompositorMutatorClient(std::move(mutator)) {}
+ : CompositorMutatorClient(std::move(mutator)), done_event_(nullptr) {}
~MockCompositorMutatorClient() override {}
// gmock cannot mock methods with move-only args so we forward it to ourself.
void SetMutationUpdate(
@@ -71,8 +77,26 @@ class MockCompositorMutatorClient : public CompositorMutatorClient {
SetMutationUpdateRef(output_state.get());
}
+ MOCK_METHOD0(NotifyAnimationsPending, void());
+
+ void NotifyAnimationsReady() override {
+ NotifyAnimationsReadyRef();
+ if (done_event_) {
+ done_event_->Signal();
+ }
+ }
+
+ MOCK_METHOD0(NotifyAnimationsReadyRef, void());
+
+ void SignalWhenComplete(WaitableEvent* done_event) {
+ done_event_ = done_event;
+ }
+
MOCK_METHOD1(SetMutationUpdateRef,
void(cc::MutatorOutputState* output_state));
+
+ private:
+ WaitableEvent* done_event_; // not owned.
};
class AnimationWorkletMutatorDispatcherImplTest : public ::testing::Test {
@@ -116,32 +140,35 @@ TEST_F(AnimationWorkletMutatorDispatcherImplTest,
RegisteredAnimatorShouldOnlyReceiveInputForItself) {
std::unique_ptr<Thread> first_thread = CreateThread("FirstThread");
MockAnimationWorkletMutator* first_mutator =
- new ::testing::StrictMock<MockAnimationWorkletMutator>(
+ MakeGarbageCollected<MockAnimationWorkletMutator>(
first_thread->GetTaskRunner());
mutator_->RegisterAnimationWorkletMutator(first_mutator,
first_thread->GetTaskRunner());
- EXPECT_CALL(*first_mutator, GetScopeId()).Times(1).WillOnce(Return(11));
+ EXPECT_CALL(*first_mutator, GetWorkletId())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return(11));
EXPECT_CALL(*first_mutator, MutateRef(Truly(OnlyIncludesAnimation1)))
.Times(1)
.WillOnce(Return(new AnimationWorkletOutput()));
EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(1);
-
- mutator_->Mutate(CreateTestMutatorInput());
+ mutator_->MutateSynchronously(CreateTestMutatorInput());
}
TEST_F(AnimationWorkletMutatorDispatcherImplTest,
RegisteredAnimatorShouldNotBeMutatedWhenNoInput) {
std::unique_ptr<Thread> first_thread = CreateThread("FirstThread");
MockAnimationWorkletMutator* first_mutator =
- new ::testing::StrictMock<MockAnimationWorkletMutator>(
+ MakeGarbageCollected<MockAnimationWorkletMutator>(
first_thread->GetTaskRunner());
mutator_->RegisterAnimationWorkletMutator(first_mutator,
first_thread->GetTaskRunner());
- EXPECT_CALL(*first_mutator, GetScopeId()).Times(1).WillOnce(Return(11));
+ EXPECT_CALL(*first_mutator, GetWorkletId())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return(11));
EXPECT_CALL(*first_mutator, MutateRef(_)).Times(0);
EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(0);
@@ -151,7 +178,7 @@ TEST_F(AnimationWorkletMutatorDispatcherImplTest,
auto input = std::make_unique<AnimationWorkletDispatcherInput>();
input->Add(std::move(state2));
- mutator_->Mutate(std::move(input));
+ mutator_->MutateSynchronously(std::move(input));
}
TEST_F(AnimationWorkletMutatorDispatcherImplTest,
@@ -159,7 +186,7 @@ TEST_F(AnimationWorkletMutatorDispatcherImplTest,
EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(0);
std::unique_ptr<AnimationWorkletDispatcherInput> input =
std::make_unique<AnimationWorkletDispatcherInput>();
- mutator_->Mutate(std::move(input));
+ mutator_->MutateSynchronously(std::move(input));
}
TEST_F(AnimationWorkletMutatorDispatcherImplTest,
@@ -167,15 +194,18 @@ TEST_F(AnimationWorkletMutatorDispatcherImplTest,
// Create a thread to run mutator tasks.
std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread");
MockAnimationWorkletMutator* first_mutator =
- new ::testing::StrictMock<MockAnimationWorkletMutator>(
+ MakeGarbageCollected<MockAnimationWorkletMutator>(
first_thread->GetTaskRunner());
mutator_->RegisterAnimationWorkletMutator(first_mutator,
first_thread->GetTaskRunner());
- EXPECT_CALL(*first_mutator, GetScopeId()).Times(1).WillOnce(Return(11));
+
+ EXPECT_CALL(*first_mutator, GetWorkletId())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return(11));
EXPECT_CALL(*first_mutator, MutateRef(_)).Times(1).WillOnce(Return(nullptr));
EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(0);
- mutator_->Mutate(CreateTestMutatorInput());
+ mutator_->MutateSynchronously(CreateTestMutatorInput());
}
TEST_F(AnimationWorkletMutatorDispatcherImplTest,
@@ -183,17 +213,20 @@ TEST_F(AnimationWorkletMutatorDispatcherImplTest,
// Create a thread to run mutator tasks.
std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread");
MockAnimationWorkletMutator* first_mutator =
- new ::testing::StrictMock<MockAnimationWorkletMutator>(
+ MakeGarbageCollected<MockAnimationWorkletMutator>(
first_thread->GetTaskRunner());
mutator_->RegisterAnimationWorkletMutator(first_mutator,
first_thread->GetTaskRunner());
- EXPECT_CALL(*first_mutator, GetScopeId()).Times(1).WillOnce(Return(11));
+
+ EXPECT_CALL(*first_mutator, GetWorkletId())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return(11));
EXPECT_CALL(*first_mutator, MutateRef(_))
.Times(1)
.WillOnce(Return(new AnimationWorkletOutput()));
EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(1);
- mutator_->Mutate(CreateTestMutatorInput());
+ mutator_->MutateSynchronously(CreateTestMutatorInput());
// The above call blocks on mutator threads running their tasks so we can
// safely verify here.
@@ -201,10 +234,12 @@ TEST_F(AnimationWorkletMutatorDispatcherImplTest,
// Ensure mutator is not invoked after unregistration.
EXPECT_CALL(*first_mutator, MutateRef(_)).Times(0);
+ EXPECT_CALL(*client_, NotifyAnimationsPending()).Times(0);
EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(0);
+ EXPECT_CALL(*client_, NotifyAnimationsReadyRef()).Times(0);
mutator_->UnregisterAnimationWorkletMutator(first_mutator);
- mutator_->Mutate(CreateTestMutatorInput());
+ mutator_->MutateSynchronously(CreateTestMutatorInput());
Mock::VerifyAndClearExpectations(client_.get());
}
@@ -212,10 +247,10 @@ TEST_F(AnimationWorkletMutatorDispatcherImplTest,
MutationUpdateInvokedCorrectlyWithTwoRegisteredAnimatorsOnSameThread) {
std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread");
MockAnimationWorkletMutator* first_mutator =
- new ::testing::StrictMock<MockAnimationWorkletMutator>(
+ MakeGarbageCollected<MockAnimationWorkletMutator>(
first_thread->GetTaskRunner());
MockAnimationWorkletMutator* second_mutator =
- new ::testing::StrictMock<MockAnimationWorkletMutator>(
+ MakeGarbageCollected<MockAnimationWorkletMutator>(
first_thread->GetTaskRunner());
mutator_->RegisterAnimationWorkletMutator(first_mutator,
@@ -223,17 +258,20 @@ TEST_F(AnimationWorkletMutatorDispatcherImplTest,
mutator_->RegisterAnimationWorkletMutator(second_mutator,
first_thread->GetTaskRunner());
- EXPECT_CALL(*first_mutator, GetScopeId()).Times(1).WillOnce(Return(11));
+ EXPECT_CALL(*first_mutator, GetWorkletId())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return(11));
EXPECT_CALL(*first_mutator, MutateRef(_))
.Times(1)
.WillOnce(Return(new AnimationWorkletOutput()));
- EXPECT_CALL(*second_mutator, GetScopeId()).Times(1).WillOnce(Return(22));
+ EXPECT_CALL(*second_mutator, GetWorkletId())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return(22));
EXPECT_CALL(*second_mutator, MutateRef(_))
.Times(1)
.WillOnce(Return(new AnimationWorkletOutput()));
-
EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(2);
- mutator_->Mutate(CreateTestMutatorInput());
+ mutator_->MutateSynchronously(CreateTestMutatorInput());
}
TEST_F(
@@ -241,12 +279,12 @@ TEST_F(
MutationUpdateInvokedCorrectlyWithTwoRegisteredAnimatorsOnDifferentThreads) {
std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread");
MockAnimationWorkletMutator* first_mutator =
- new ::testing::StrictMock<MockAnimationWorkletMutator>(
+ MakeGarbageCollected<MockAnimationWorkletMutator>(
first_thread->GetTaskRunner());
std::unique_ptr<Thread> second_thread = CreateThread("SecondAnimationThread");
MockAnimationWorkletMutator* second_mutator =
- new ::testing::StrictMock<MockAnimationWorkletMutator>(
+ MakeGarbageCollected<MockAnimationWorkletMutator>(
second_thread->GetTaskRunner());
mutator_->RegisterAnimationWorkletMutator(first_mutator,
@@ -254,35 +292,364 @@ TEST_F(
mutator_->RegisterAnimationWorkletMutator(second_mutator,
second_thread->GetTaskRunner());
- EXPECT_CALL(*first_mutator, GetScopeId()).Times(1).WillOnce(Return(11));
+ EXPECT_CALL(*first_mutator, GetWorkletId())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return(11));
EXPECT_CALL(*first_mutator, MutateRef(_))
.Times(1)
.WillOnce(Return(new AnimationWorkletOutput()));
- EXPECT_CALL(*second_mutator, GetScopeId()).Times(1).WillOnce(Return(22));
+ EXPECT_CALL(*second_mutator, GetWorkletId())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return(22));
EXPECT_CALL(*second_mutator, MutateRef(_))
.Times(1)
.WillOnce(Return(new AnimationWorkletOutput()));
EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(2);
- mutator_->Mutate(CreateTestMutatorInput());
+ mutator_->MutateSynchronously(CreateTestMutatorInput());
// The above call blocks on mutator threads running their tasks so we can
// safely verify here.
Mock::VerifyAndClearExpectations(client_.get());
- // Ensure mutator is not invoked after unregistration.
+ // Ensure first_mutator is not invoked after unregistration.
mutator_->UnregisterAnimationWorkletMutator(first_mutator);
- EXPECT_CALL(*first_mutator, GetScopeId()).Times(0);
+ EXPECT_CALL(*first_mutator, GetWorkletId()).Times(0);
EXPECT_CALL(*first_mutator, MutateRef(_)).Times(0);
- EXPECT_CALL(*second_mutator, GetScopeId()).Times(1).WillOnce(Return(22));
+ EXPECT_CALL(*second_mutator, GetWorkletId())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return(22));
EXPECT_CALL(*second_mutator, MutateRef(_))
.Times(1)
.WillOnce(Return(new AnimationWorkletOutput()));
EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(1);
- mutator_->Mutate(CreateTestMutatorInput());
+ mutator_->MutateSynchronously(CreateTestMutatorInput());
+
Mock::VerifyAndClearExpectations(client_.get());
}
+// -----------------------------------------------------------------------
+// Asynchronous version of tests.
+
+// Callback wrapping portion of the async test that is required to run on the
+// compositor thread.
+using MutateAsyncCallback = WTF::CrossThreadFunction<void()>;
+
+using MutatorDispatcherRef =
+ scoped_refptr<AnimationWorkletMutatorDispatcherImpl>;
+
+class AnimationWorkletMutatorDispatcherImplAsyncTest
+ : public AnimationWorkletMutatorDispatcherImplTest {
+ public:
+ void SetUp() override {
+ if (!Thread::CompositorThread()) {
+ Thread::CreateAndSetCompositorThread();
+ }
+ AnimationWorkletMutatorDispatcherImplTest::SetUp();
+ }
+
+ // Call this version of mutate and wait if expecting a mutate completion
+ // notification from the client.
+ void CallMutateAndWaitForClientCompletion(
+ MutateAsyncCallback mutate_callback) {
+ WaitableEvent done_event;
+ client_->SignalWhenComplete(&done_event);
+ PostCrossThreadTask(*Thread::CompositorThread()->GetTaskRunner(), FROM_HERE,
+ std::move(mutate_callback));
+ done_event.Wait();
+ }
+
+ // Call this version of mutate and wait if there is no expectation of client
+ // notifications. There are no notificaitons if the mutate call is a no-op
+ // such as when there are no inputs.
+ void CallMutateAndWaitForCallbackCompletion(
+ MutateAsyncCallback mutate_callback) {
+ WaitableEvent done_event;
+ PostCrossThreadTask(
+ *Thread::CompositorThread()->GetTaskRunner(), FROM_HERE,
+ CrossThreadBind(
+ [](MutateAsyncCallback mutate_callback, WaitableEvent* done_event) {
+ mutate_callback.Run();
+ done_event->Signal();
+ },
+ WTF::Passed(std::move(mutate_callback)),
+ WTF::CrossThreadUnretained(&done_event)));
+ done_event.Wait();
+ }
+};
+
+TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,
+ RegisteredAnimatorShouldOnlyReceiveInputForItself) {
+ std::unique_ptr<Thread> first_thread = CreateThread("FirstThread");
+ MockAnimationWorkletMutator* first_mutator =
+ MakeGarbageCollected<MockAnimationWorkletMutator>(
+ first_thread->GetTaskRunner());
+
+ // Call MutateAsynchronously from the compositor thread.
+ MutateAsyncCallback mutate_callback = CrossThreadBind(
+ [](std::unique_ptr<Thread> first_thread,
+ MockAnimationWorkletMutator* first_mutator,
+ AnimationWorkletMutatorDispatcherImplAsyncTest* async_test) {
+ async_test->mutator_->RegisterAnimationWorkletMutator(
+ first_mutator, first_thread->GetTaskRunner());
+ async_test->mutator_->MutateAsynchronously(CreateTestMutatorInput());
+ },
+ WTF::Passed(std::move(first_thread)),
+ WrapCrossThreadWeakPersistent(first_mutator),
+ WTF::CrossThreadUnretained(this));
+
+ Sequence s;
+ EXPECT_CALL(*first_mutator, GetWorkletId())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return(11));
+ EXPECT_CALL(*first_mutator, MutateRef(_))
+ .Times(1)
+ .WillOnce(Return(new AnimationWorkletOutput()));
+ EXPECT_CALL(*client_, NotifyAnimationsPending()).Times(1).InSequence(s);
+ EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(1).InSequence(s);
+ EXPECT_CALL(*client_, NotifyAnimationsReadyRef()).Times(1).InSequence(s);
+ CallMutateAndWaitForClientCompletion(std::move(mutate_callback));
+}
+
+TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,
+ RegisteredAnimatorShouldNotBeMutatedWhenNoInput) {
+ std::unique_ptr<Thread> first_thread = CreateThread("FirstThread");
+ MockAnimationWorkletMutator* first_mutator =
+ MakeGarbageCollected<MockAnimationWorkletMutator>(
+ first_thread->GetTaskRunner());
+
+ // Call MutateAsynchronously from the compositor thread.
+ MutateAsyncCallback mutate_callback = CrossThreadBind(
+ [](std::unique_ptr<Thread> first_thread,
+ MockAnimationWorkletMutator* first_mutator,
+ AnimationWorkletMutatorDispatcherImplAsyncTest* async_test) {
+ async_test->mutator_->RegisterAnimationWorkletMutator(
+ first_mutator, first_thread->GetTaskRunner());
+
+ AnimationWorkletInput::AddAndUpdateState state2{
+ {22, 2}, "test2", 5000, nullptr, 1};
+
+ auto input = std::make_unique<AnimationWorkletDispatcherInput>();
+ input->Add(std::move(state2));
+
+ async_test->mutator_->MutateAsynchronously(std::move(input));
+ },
+ WTF::Passed(std::move(first_thread)),
+ WrapCrossThreadWeakPersistent(first_mutator),
+ WTF::CrossThreadUnretained(this));
+
+ // The start of the mutation process will be synchronous. If a pending
+ // notification is not received by the time the callback returns, it will not
+ // be triggered later.
+ EXPECT_CALL(*first_mutator, GetWorkletId())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return(11));
+ EXPECT_CALL(*client_, NotifyAnimationsPending()).Times(0);
+ CallMutateAndWaitForCallbackCompletion(std::move(mutate_callback));
+}
+
+TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,
+ MutationUpdateIsNotInvokedWithNoRegisteredAnimators) {
+ // Call MutateAsynchronously from the compositor thread.
+ MutateAsyncCallback mutate_callback = CrossThreadBind(
+ [](AnimationWorkletMutatorDispatcherImplAsyncTest* async_test) {
+ std::unique_ptr<AnimationWorkletDispatcherInput> input =
+ std::make_unique<AnimationWorkletDispatcherInput>();
+ async_test->mutator_->MutateAsynchronously(std::move(input));
+ },
+ WTF::CrossThreadUnretained(this));
+
+ // The start of the mutation process will be synchronous. If a pending
+ // notification is not received by the time the callback returns, it will not
+ // be triggered later.
+ EXPECT_CALL(*client_, NotifyAnimationsPending()).Times(0);
+ CallMutateAndWaitForCallbackCompletion(std::move(mutate_callback));
+}
+
+TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,
+ MutationUpdateIsNotInvokedWithNullOutput) {
+ // Create a thread to run mutator tasks.
+ std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread");
+ MockAnimationWorkletMutator* first_mutator =
+ MakeGarbageCollected<MockAnimationWorkletMutator>(
+ first_thread->GetTaskRunner());
+
+ // Call MutateAsynchronously from the compositor thread.
+ MutateAsyncCallback mutate_callback = CrossThreadBind(
+ [](std::unique_ptr<Thread> first_thread,
+ MockAnimationWorkletMutator* first_mutator,
+ AnimationWorkletMutatorDispatcherImplAsyncTest* async_test) {
+ async_test->mutator_->RegisterAnimationWorkletMutator(
+ first_mutator, first_thread->GetTaskRunner());
+ async_test->mutator_->MutateAsynchronously(CreateTestMutatorInput());
+ },
+ WTF::Passed(std::move(first_thread)),
+ WrapCrossThreadWeakPersistent(first_mutator),
+ WTF::CrossThreadUnretained(this));
+
+ Sequence s;
+ EXPECT_CALL(*first_mutator, GetWorkletId())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return(11));
+ EXPECT_CALL(*first_mutator, MutateRef(_)).Times(1).WillOnce(Return(nullptr));
+ EXPECT_CALL(*client_, NotifyAnimationsPending()).Times(1).InSequence(s);
+ EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(0);
+ EXPECT_CALL(*client_, NotifyAnimationsReadyRef()).Times(1).InSequence(s);
+ CallMutateAndWaitForClientCompletion(std::move(mutate_callback));
+}
+
+TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,
+ MutationUpdateIsInvokedCorrectlyWithSingleRegisteredAnimator) {
+ // Create a thread to run mutator tasks.
+ std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread");
+ MockAnimationWorkletMutator* first_mutator =
+ MakeGarbageCollected<MockAnimationWorkletMutator>(
+ first_thread->GetTaskRunner());
+
+ // Call MutateAsynchronously from the compositor thread.
+ MutateAsyncCallback mutate_callback = CrossThreadBind(
+ [](std::unique_ptr<Thread> first_thread,
+ MockAnimationWorkletMutator* first_mutator,
+ AnimationWorkletMutatorDispatcherImplAsyncTest* async_test) {
+ async_test->mutator_->RegisterAnimationWorkletMutator(
+ first_mutator, first_thread->GetTaskRunner());
+ async_test->mutator_->MutateAsynchronously(CreateTestMutatorInput());
+ },
+ WTF::Passed(std::move(first_thread)),
+ WrapCrossThreadWeakPersistent(first_mutator),
+ WTF::CrossThreadUnretained(this));
+
+ Sequence s;
+ EXPECT_CALL(*first_mutator, GetWorkletId())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return(11));
+ EXPECT_CALL(*first_mutator, MutateRef(_))
+ .Times(1)
+ .WillOnce(Return(new AnimationWorkletOutput()));
+ EXPECT_CALL(*client_, NotifyAnimationsPending()).Times(1).InSequence(s);
+ EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(1).InSequence(s);
+ EXPECT_CALL(*client_, NotifyAnimationsReadyRef()).Times(1).InSequence(s);
+ CallMutateAndWaitForClientCompletion(std::move(mutate_callback));
+
+ // Above call blocks until complete signal is received.
+ Mock::VerifyAndClearExpectations(client_.get());
+
+ // Call MutateAsynchronously from the compositor thread.
+ MutateAsyncCallback mutate_callback2 = CrossThreadBind(
+ [](MockAnimationWorkletMutator* first_mutator,
+ AnimationWorkletMutatorDispatcherImplAsyncTest* async_test) {
+ // Ensure mutator is not invoked after unregistration.
+ async_test->mutator_->UnregisterAnimationWorkletMutator(first_mutator);
+ async_test->mutator_->MutateAsynchronously(CreateTestMutatorInput());
+ },
+ WrapCrossThreadWeakPersistent(first_mutator),
+ WTF::CrossThreadUnretained(this));
+
+ // The start of the mutation process will be synchronous. If a pending
+ // notification is not received by the time the callback returns, it will not
+ // be triggered later.
+ EXPECT_CALL(*client_, NotifyAnimationsPending()).Times(0);
+ CallMutateAndWaitForCallbackCompletion(std::move(mutate_callback2));
+ Mock::VerifyAndClearExpectations(client_.get());
+}
+
+TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,
+ MutationUpdateInvokedCorrectlyWithTwoRegisteredAnimatorsOnSameThread) {
+ std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread");
+ MockAnimationWorkletMutator* first_mutator =
+ MakeGarbageCollected<MockAnimationWorkletMutator>(
+ first_thread->GetTaskRunner());
+ MockAnimationWorkletMutator* second_mutator =
+ MakeGarbageCollected<MockAnimationWorkletMutator>(
+ first_thread->GetTaskRunner());
+
+ // Call MutateAsynchronously from the compositor thread.
+ MutateAsyncCallback mutate_callback = CrossThreadBind(
+ [](std::unique_ptr<Thread> first_thread,
+ MockAnimationWorkletMutator* first_mutator,
+ MockAnimationWorkletMutator* second_mutator,
+ AnimationWorkletMutatorDispatcherImplAsyncTest* async_test) {
+ async_test->mutator_->RegisterAnimationWorkletMutator(
+ first_mutator, first_thread->GetTaskRunner());
+ async_test->mutator_->RegisterAnimationWorkletMutator(
+ second_mutator, first_thread->GetTaskRunner());
+ async_test->mutator_->MutateAsynchronously(CreateTestMutatorInput());
+ },
+ WTF::Passed(std::move(first_thread)),
+ WrapCrossThreadWeakPersistent(first_mutator),
+ WrapCrossThreadWeakPersistent(second_mutator),
+ WTF::CrossThreadUnretained(this));
+
+ Sequence s;
+ EXPECT_CALL(*first_mutator, GetWorkletId())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return(11));
+ EXPECT_CALL(*first_mutator, MutateRef(_))
+ .Times(1)
+ .WillOnce(Return(new AnimationWorkletOutput()));
+ EXPECT_CALL(*second_mutator, GetWorkletId())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return(22));
+ EXPECT_CALL(*second_mutator, MutateRef(_))
+ .Times(1)
+ .WillOnce(Return(new AnimationWorkletOutput()));
+ EXPECT_CALL(*client_, NotifyAnimationsPending()).Times(1).InSequence(s);
+ EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(2).InSequence(s);
+ EXPECT_CALL(*client_, NotifyAnimationsReadyRef()).Times(1).InSequence(s);
+ CallMutateAndWaitForClientCompletion(std::move(mutate_callback));
+}
+
+TEST_F(
+ AnimationWorkletMutatorDispatcherImplAsyncTest,
+ MutationUpdateInvokedCorrectlyWithTwoRegisteredAnimatorsOnDifferentThreads) {
+ std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread");
+ MockAnimationWorkletMutator* first_mutator =
+ MakeGarbageCollected<MockAnimationWorkletMutator>(
+ first_thread->GetTaskRunner());
+
+ std::unique_ptr<Thread> second_thread = CreateThread("SecondAnimationThread");
+ MockAnimationWorkletMutator* second_mutator =
+ MakeGarbageCollected<MockAnimationWorkletMutator>(
+ second_thread->GetTaskRunner());
+
+ // Call MutateAsynchronously from the compositor thread.
+ MutateAsyncCallback mutate_callback = CrossThreadBind(
+ [](std::unique_ptr<Thread> first_thread,
+ std::unique_ptr<Thread> second_thread,
+ MockAnimationWorkletMutator* first_mutator,
+ MockAnimationWorkletMutator* second_mutator,
+ AnimationWorkletMutatorDispatcherImplAsyncTest* async_test) {
+ async_test->mutator_->RegisterAnimationWorkletMutator(
+ first_mutator, first_thread->GetTaskRunner());
+ async_test->mutator_->RegisterAnimationWorkletMutator(
+ second_mutator, second_thread->GetTaskRunner());
+ async_test->mutator_->MutateAsynchronously(CreateTestMutatorInput());
+ },
+ WTF::Passed(std::move(first_thread)),
+ WTF::Passed(std::move(second_thread)),
+ WrapCrossThreadWeakPersistent(first_mutator),
+ WrapCrossThreadWeakPersistent(second_mutator),
+ WTF::CrossThreadUnretained(this));
+
+ Sequence s;
+ EXPECT_CALL(*first_mutator, GetWorkletId())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return(11));
+ EXPECT_CALL(*first_mutator, MutateRef(_))
+ .Times(1)
+ .WillOnce(Return(new AnimationWorkletOutput()));
+ EXPECT_CALL(*second_mutator, GetWorkletId())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return(22));
+ EXPECT_CALL(*second_mutator, MutateRef(_))
+ .Times(1)
+ .WillOnce(Return(new AnimationWorkletOutput()));
+ EXPECT_CALL(*client_, NotifyAnimationsPending()).Times(1).InSequence(s);
+ EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(2).InSequence(s);
+ EXPECT_CALL(*client_, NotifyAnimationsReadyRef()).Times(1).InSequence(s);
+ CallMutateAndWaitForClientCompletion(std::move(mutate_callback));
+}
+
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc
index 0fdd3dd61b2..8a56e382d36 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc
@@ -99,7 +99,7 @@ void BitmapImage::NotifyMemoryChanged() {
size_t BitmapImage::TotalFrameBytes() {
if (cached_frame_)
- return Size().Area() * sizeof(ImageFrame::PixelData);
+ return static_cast<size_t>(Size().Area()) * sizeof(ImageFrame::PixelData);
return 0u;
}
@@ -182,8 +182,8 @@ Image::SizeAvailability BitmapImage::SetData(scoped_refptr<SharedBuffer> data,
// Return the image density in 0.01 "bits per pixel" rounded to the nearest
// integer.
-static inline int ImageDensityInCentiBpp(IntSize size,
- size_t image_size_bytes) {
+static inline uint64_t ImageDensityInCentiBpp(IntSize size,
+ size_t image_size_bytes) {
uint64_t image_area = static_cast<uint64_t>(size.Width()) * size.Height();
return (static_cast<uint64_t>(image_size_bytes) * 100 * 8 + image_area / 2) /
image_area;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc
index 3158dc5f284..965892c862e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc
@@ -46,24 +46,27 @@ void BitmapImageMetrics::CountImageOrientation(
}
void BitmapImageMetrics::CountImageJpegDensity(int image_min_side,
- int64_t density_centi_bpp) {
+ uint64_t density_centi_bpp) {
// Values are reported in the range 0.01 to 10 bpp, in different metrics
// depending on the image category (small, medium, large).
if (image_min_side >= 1000) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(
CustomCountHistogram, density_histogram,
("Blink.DecodedImage.JpegDensity.1000px", 1, 1000, 100));
- density_histogram.Count(density_centi_bpp);
+ density_histogram.Count(
+ base::saturated_cast<base::Histogram::Sample>(density_centi_bpp));
} else if (image_min_side >= 400) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(
CustomCountHistogram, density_histogram,
("Blink.DecodedImage.JpegDensity.400px", 1, 1000, 100));
- density_histogram.Count(density_centi_bpp);
+ density_histogram.Count(
+ base::saturated_cast<base::Histogram::Sample>(density_centi_bpp));
} else if (image_min_side >= 100) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(
CustomCountHistogram, density_histogram,
("Blink.DecodedImage.JpegDensity.100px", 1, 1000, 100));
- density_histogram.Count(density_centi_bpp);
+ density_histogram.Count(
+ base::saturated_cast<base::Histogram::Sample>(density_centi_bpp));
} else {
// We don't report for images with 0 to 99px on the smallest dimension.
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h
index 3479690b4e5..ab67d76ca28 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h
@@ -77,7 +77,7 @@ class PLATFORM_EXPORT BitmapImageMetrics {
// Report the JPEG compression density in 0.01 bits per pixel for an image
// with a smallest side (width or length) of |image_min_side|.
static void CountImageJpegDensity(int image_min_side,
- int64_t density_centi_bpp);
+ uint64_t density_centi_bpp);
static void CountImageGammaAndGamut(const skcms_ICCProfile*);
static void CountJpegArea(const IntSize& size);
static void CountJpegColorSpace(JpegColorSpace color_space);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image_test.cc b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image_test.cc
index 616b61d76b9..618a32a8f91 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image_test.cc
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/platform/graphics/bitmap_image.h"
#include "base/test/simple_test_tick_clock.h"
+#include "cc/paint/image_provider.h"
#include "cc/paint/skia_paint_canvas.h"
#include "cc/tiles/mipmap_util.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -233,7 +234,7 @@ class BitmapImageTest : public testing::Test {
protected:
void SetUp() override {
- image_observer_ = new FakeImageObserver;
+ image_observer_ = MakeGarbageCollected<FakeImageObserver>();
image_ = BitmapImage::Create(image_observer_.Get());
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
index ca6a5261754..594dd36935a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
@@ -33,6 +33,7 @@
#include "cc/layers/texture_layer.h"
#include "components/viz/common/resources/transferable_resource.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/graphics/canvas_heuristic_parameters.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource.h"
@@ -141,6 +142,9 @@ void Canvas2DLayerBridge::ResetResourceProvider() {
}
bool Canvas2DLayerBridge::ShouldAccelerate(AccelerationHint hint) const {
+ if (base::FeatureList::IsEnabled(features::kAlwaysAccelerateCanvas)) {
+ return true;
+ }
bool accelerate;
if (software_rendering_while_hidden_) {
accelerate = false;
@@ -601,13 +605,12 @@ bool Canvas2DLayerBridge::PrepareTransferableResource(
return false;
scoped_refptr<CanvasResource> frame = ResourceProvider()->ProduceFrame();
- if (frame && frame->IsValid()) {
- // Note frame is kept alive via a reference kept in out_release_callback.
- bool success = frame->PrepareTransferableResource(
- out_resource, out_release_callback, kUnverifiedSyncToken);
- return success;
- }
- return false;
+ if (!frame || !frame->IsValid())
+ return false;
+
+ // Note frame is kept alive via a reference kept in out_release_callback.
+ return frame->PrepareTransferableResource(out_resource, out_release_callback,
+ kUnverifiedSyncToken);
}
cc::Layer* Canvas2DLayerBridge::Layer() {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h b/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h
index 326c4f6727f..02c3c1c3528 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h
@@ -193,7 +193,7 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
friend class Canvas2DLayerBridgeTest;
friend class CanvasRenderingContext2DTest;
- friend class HTMLCanvasPainterTestForSPv2;
+ friend class HTMLCanvasPainterTestForCAP;
AccelerationMode acceleration_mode_;
CanvasColorParams color_params_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
index e3079a828ba..cdcba06eaa4 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
@@ -140,24 +140,24 @@ sk_sp<SkColorSpace> CanvasColorParams::GetSkColorSpace() const {
sk_sp<SkColorSpace> CanvasColorParams::CanvasColorSpaceToSkColorSpace(
CanvasColorSpace color_space) {
- SkColorSpace::Gamut gamut = SkColorSpace::kSRGB_Gamut;
- SkColorSpace::RenderTargetGamma gamma = SkColorSpace::kSRGB_RenderTargetGamma;
+ skcms_Matrix3x3 gamut = SkNamedGamut::kSRGB;
+ skcms_TransferFunction transferFn = SkNamedTransferFn::kSRGB;
switch (color_space) {
case kSRGBCanvasColorSpace:
break;
case kLinearRGBCanvasColorSpace:
- gamma = SkColorSpace::kLinear_RenderTargetGamma;
+ transferFn = SkNamedTransferFn::kLinear;
break;
case kRec2020CanvasColorSpace:
- gamut = SkColorSpace::kRec2020_Gamut;
- gamma = SkColorSpace::kLinear_RenderTargetGamma;
+ gamut = SkNamedGamut::kRec2020;
+ transferFn = SkNamedTransferFn::kLinear;
break;
case kP3CanvasColorSpace:
- gamut = SkColorSpace::kDCIP3_D65_Gamut;
- gamma = SkColorSpace::kLinear_RenderTargetGamma;
+ gamut = SkNamedGamut::kDCIP3;
+ transferFn = SkNamedTransferFn::kLinear;
break;
}
- return SkColorSpace::MakeRGB(gamma, gamut);
+ return SkColorSpace::MakeRGB(transferFn, gamut);
}
gfx::BufferFormat CanvasColorParams::GetBufferFormat() const {
@@ -240,14 +240,14 @@ CanvasColorParams::CanvasColorParams(const sk_sp<SkColorSpace> color_space,
color_space_ = kLinearRGBCanvasColorSpace;
} else if (SkColorSpace::Equals(
color_space.get(),
- SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma,
- SkColorSpace::kRec2020_Gamut)
+ SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear,
+ SkNamedGamut::kRec2020)
.get())) {
color_space_ = kRec2020CanvasColorSpace;
} else if (SkColorSpace::Equals(
color_space.get(),
- SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma,
- SkColorSpace::kDCIP3_D65_Gamut)
+ SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear,
+ SkNamedGamut::kDCIP3)
.get())) {
color_space_ = kP3CanvasColorSpace;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc
index 69d5a9a547f..46bb27f2346 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -82,12 +82,10 @@ static void ReleaseFrameResources(
const gpu::SyncToken& sync_token,
bool lost_resource) {
resource->WaitSyncToken(sync_token);
- if (lost_resource) {
+ if (lost_resource)
resource->Abandon();
- }
- if (resource_provider && !lost_resource && resource->IsRecycleable()) {
+ if (resource_provider && !lost_resource && resource->IsRecycleable())
resource_provider->RecycleResource(std::move(resource));
- }
}
bool CanvasResource::PrepareTransferableResource(
@@ -116,7 +114,8 @@ bool CanvasResource::PrepareAcceleratedTransferableResource(
// Gpu compositing is a prerequisite for compositing an accelerated resource
DCHECK(SharedGpuContext::IsGpuCompositingEnabled());
auto* gl = ContextGL();
- DCHECK(gl);
+ if (!gl)
+ return false;
const gpu::Mailbox& mailbox = GetOrCreateGpuMailbox(sync_mode);
if (mailbox.IsZero())
return false;
@@ -413,7 +412,6 @@ void CanvasResourceGpuMemoryBuffer::Abandon() {
const gpu::Mailbox& CanvasResourceGpuMemoryBuffer::GetOrCreateGpuMailbox(
MailboxSyncMode sync_mode) {
auto* gl = ContextGL();
- DCHECK(gl); // caller should already have early exited if !gl.
if (gpu_mailbox_.IsZero() && gl) {
gl->ProduceTextureDirectCHROMIUM(texture_id_, gpu_mailbox_.name);
mailbox_needs_new_sync_token_ = true;
@@ -431,16 +429,17 @@ GLuint CanvasResourceGpuMemoryBuffer::GetBackingTextureHandleForOverwrite() {
}
const gpu::SyncToken CanvasResourceGpuMemoryBuffer::GetSyncToken() {
- if (mailbox_needs_new_sync_token_) {
- auto* gl = ContextGL();
- DCHECK(gl); // caller should already have early exited if !gl.
- mailbox_needs_new_sync_token_ = false;
- if (mailbox_sync_mode_ == kVerifiedSyncToken) {
- gl->GenSyncTokenCHROMIUM(sync_token_.GetData());
- } else {
- gl->GenUnverifiedSyncTokenCHROMIUM(sync_token_.GetData());
- }
- }
+ if (!mailbox_needs_new_sync_token_)
+ return sync_token_;
+ auto* gl = ContextGL();
+ if (!gl)
+ return sync_token_;
+ mailbox_needs_new_sync_token_ = false;
+ if (mailbox_sync_mode_ == kVerifiedSyncToken)
+ gl->GenSyncTokenCHROMIUM(sync_token_.GetData());
+ else
+ gl->GenUnverifiedSyncTokenCHROMIUM(sync_token_.GetData());
+
return sync_token_;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc
index d66820e97e0..75731e65285 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc
@@ -60,7 +60,7 @@ CanvasResourceDispatcher::CanvasResourceDispatcher(
num_unreclaimed_frames_posted_(0),
client_(client),
enable_surface_synchronization_(
- features::IsSurfaceSynchronizationEnabled()),
+ ::features::IsSurfaceSynchronizationEnabled()),
weak_ptr_factory_(this) {
// Frameless canvas pass an invalid |frame_sink_id_|; don't create mojo
// channel for this special case.
@@ -75,8 +75,9 @@ CanvasResourceDispatcher::CanvasResourceDispatcher(
DCHECK(provider);
binding_.Bind(mojo::MakeRequest(&client_ptr_));
provider->CreateCompositorFrameSink(frame_sink_id_, std::move(client_ptr_),
- mojo::MakeRequest(&sink_),
- mojo::MakeRequest(&surface_embedder_));
+ mojo::MakeRequest(&sink_));
+ provider->ConnectToEmbedder(frame_sink_id_,
+ mojo::MakeRequest(&surface_embedder_));
}
CanvasResourceDispatcher::~CanvasResourceDispatcher() = default;
@@ -218,6 +219,8 @@ bool CanvasResourceDispatcher::PrepareFrame(
}
frame->metadata.begin_frame_ack = current_begin_frame_ack_;
+ frame->metadata.frame_token = ++next_frame_token_;
+
const gfx::Rect bounds(size_.Width(), size_.Height());
constexpr int kRenderPassId = 1;
constexpr bool is_clipped = false;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h
index 299818c4434..cee6b36546f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h
@@ -120,6 +120,8 @@ class PLATFORM_EXPORT CanvasResourceDispatcher
unsigned next_resource_id_ = 0;
ResourceMap resources_;
+ viz::FrameTokenGenerator next_frame_token_;
+
// The latest_unposted_resource_id_ always refers to the Id of the frame
// resource used by the latest_unposted_image_.
scoped_refptr<CanvasResource> latest_unposted_image_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
index d04b01988af..e282da6a595 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
#include "base/metrics/histogram_functions.h"
+#include "base/stl_util.h"
#include "cc/paint/decode_stashing_image_provider.h"
#include "cc/tiles/software_image_decode_cache.h"
#include "components/viz/common/resources/resource_format_utils.h"
@@ -435,53 +436,84 @@ class CanvasResourceProviderDirectGpuMemoryBuffer final
scoped_refptr<CanvasResource> resource_;
};
-enum CanvasResourceType {
- kDirectGpuMemoryBufferResourceType,
- kTextureGpuMemoryBufferResourceType,
- kBitmapGpuMemoryBufferResourceType,
- kSharedBitmapResourceType,
- kTextureResourceType,
- kBitmapResourceType,
-};
-
-constexpr CanvasResourceType kSoftwareCompositedFallbackList[] = {
- kBitmapGpuMemoryBufferResourceType,
- kSharedBitmapResourceType,
- // Fallback to no direct compositing support
- kBitmapResourceType,
-};
+namespace {
-constexpr CanvasResourceType kSoftwareFallbackList[] = {
- kBitmapResourceType,
+enum class CanvasResourceType {
+ kDirectGpuMemoryBuffer,
+ kTextureGpuMemoryBuffer,
+ kBitmapGpuMemoryBuffer,
+ kSharedBitmap,
+ kTexture,
+ kBitmap,
};
-constexpr CanvasResourceType kAcceleratedFallbackList[] = {
- kTextureResourceType,
- // Fallback to software
- kBitmapResourceType,
-};
+const std::vector<CanvasResourceType>& GetResourceTypeFallbackList(
+ CanvasResourceProvider::ResourceUsage usage) {
+ static const std::vector<CanvasResourceType> kSoftwareFallbackList({
+ CanvasResourceType::kBitmap,
+ });
+
+ static const std::vector<CanvasResourceType> kAcceleratedFallbackList({
+ CanvasResourceType::kTexture,
+ // Fallback to software
+ CanvasResourceType::kBitmap,
+ });
+
+ static const std::vector<CanvasResourceType> kSoftwareCompositedFallbackList({
+ CanvasResourceType::kBitmapGpuMemoryBuffer,
+ CanvasResourceType::kSharedBitmap,
+ // Fallback to no direct compositing support
+ CanvasResourceType::kBitmap,
+ });
+
+ static const std::vector<CanvasResourceType>
+ kAcceleratedCompositedFallbackList({
+ CanvasResourceType::kTextureGpuMemoryBuffer,
+ CanvasResourceType::kTexture,
+ // Fallback to software composited
+ // (|kSoftwareCompositedFallbackList|).
+ CanvasResourceType::kBitmapGpuMemoryBuffer,
+ CanvasResourceType::kSharedBitmap,
+ // Fallback to no direct compositing support
+ CanvasResourceType::kBitmap,
+ });
+ DCHECK(std::equal(kAcceleratedCompositedFallbackList.begin() + 2,
+ kAcceleratedCompositedFallbackList.end(),
+ kSoftwareCompositedFallbackList.begin(),
+ kSoftwareCompositedFallbackList.end()));
+
+ static const std::vector<CanvasResourceType> kAcceleratedDirectFallbackList({
+ CanvasResourceType::kDirectGpuMemoryBuffer,
+ // The rest is equal to |kAcceleratedCompositedFallbackList|.
+ CanvasResourceType::kTextureGpuMemoryBuffer,
+ CanvasResourceType::kTexture,
+ // Fallback to software composited
+ CanvasResourceType::kBitmapGpuMemoryBuffer,
+ CanvasResourceType::kSharedBitmap,
+ // Fallback to no direct compositing support
+ CanvasResourceType::kBitmap,
+ });
+ DCHECK(std::equal(kAcceleratedDirectFallbackList.begin() + 1,
+ kAcceleratedDirectFallbackList.end(),
+ kAcceleratedCompositedFallbackList.begin(),
+ kAcceleratedCompositedFallbackList.end()));
-constexpr CanvasResourceType kAcceleratedCompositedFallbackList[] = {
- kTextureGpuMemoryBufferResourceType,
- kTextureResourceType,
- // Fallback to software composited
- kBitmapGpuMemoryBufferResourceType,
- kSharedBitmapResourceType,
- // Fallback to no direct compositing support
- kBitmapResourceType,
-};
+ switch (usage) {
+ case CanvasResourceProvider::kSoftwareResourceUsage:
+ return kSoftwareFallbackList;
+ case CanvasResourceProvider::kSoftwareCompositedResourceUsage:
+ return kSoftwareCompositedFallbackList;
+ case CanvasResourceProvider::kAcceleratedResourceUsage:
+ return kAcceleratedFallbackList;
+ case CanvasResourceProvider::kAcceleratedCompositedResourceUsage:
+ return kAcceleratedCompositedFallbackList;
+ case CanvasResourceProvider::kAcceleratedDirectResourceUsage:
+ return kAcceleratedDirectFallbackList;
+ }
+ NOTREACHED();
+}
-constexpr CanvasResourceType kAcceleratedDirectFallbackList[] = {
- kDirectGpuMemoryBufferResourceType,
- // The rest is equal to |kAcceleratedCompositedFallbackList|.
- kTextureGpuMemoryBufferResourceType,
- kTextureResourceType,
- // Fallback to software composited
- kBitmapGpuMemoryBufferResourceType,
- kSharedBitmapResourceType,
- // Fallback to no direct compositing support
- kBitmapResourceType,
-};
+} // unnamed namespace
std::unique_ptr<CanvasResourceProvider> CanvasResourceProvider::Create(
const IntSize& size,
@@ -492,41 +524,17 @@ std::unique_ptr<CanvasResourceProvider> CanvasResourceProvider::Create(
PresentationMode presentation_mode,
base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher,
bool is_origin_top_left) {
- const CanvasResourceType* resource_type_fallback_list = nullptr;
- size_t list_length = 0;
-
- switch (usage) {
- case kSoftwareResourceUsage:
- resource_type_fallback_list = kSoftwareFallbackList;
- list_length = arraysize(kSoftwareFallbackList);
- break;
- case kSoftwareCompositedResourceUsage:
- resource_type_fallback_list = kSoftwareCompositedFallbackList;
- list_length = arraysize(kSoftwareCompositedFallbackList);
- break;
- case kAcceleratedResourceUsage:
- resource_type_fallback_list = kAcceleratedFallbackList;
- list_length = arraysize(kAcceleratedFallbackList);
- break;
- case kAcceleratedCompositedResourceUsage:
- resource_type_fallback_list = kAcceleratedCompositedFallbackList;
- list_length = arraysize(kAcceleratedCompositedFallbackList);
- break;
- case kAcceleratedDirectResourceUsage:
- resource_type_fallback_list = kAcceleratedDirectFallbackList;
- list_length = arraysize(kAcceleratedDirectFallbackList);
- break;
- }
-
std::unique_ptr<CanvasResourceProvider> provider;
- for (size_t i = 0; i < list_length; ++i) {
+ const std::vector<CanvasResourceType>& fallback_list =
+ GetResourceTypeFallbackList(usage);
+ for (CanvasResourceType resource_type : fallback_list) {
// Note: We are deliberately not using std::move() on
// |context_provider_wrapper| and |resource_dispatcher| to ensure that the
// pointers remain valid for the next iteration of this loop if necessary.
- switch (resource_type_fallback_list[i]) {
- case kTextureGpuMemoryBufferResourceType:
+ switch (resource_type) {
+ case CanvasResourceType::kTextureGpuMemoryBuffer:
FALLTHROUGH;
- case kDirectGpuMemoryBufferResourceType:
+ case CanvasResourceType::kDirectGpuMemoryBuffer:
if (!SharedGpuContext::IsGpuCompositingEnabled())
continue;
if (presentation_mode != kAllowImageChromiumPresentationMode)
@@ -546,8 +554,7 @@ std::unique_ptr<CanvasResourceProvider> CanvasResourceProvider::Create(
DCHECK_EQ(color_params.GLUnsizedInternalFormat(),
gpu::InternalFormatForGpuMemoryBufferFormat(
color_params.GetBufferFormat()));
- if (resource_type_fallback_list[i] ==
- kDirectGpuMemoryBufferResourceType) {
+ if (resource_type == CanvasResourceType::kDirectGpuMemoryBuffer) {
provider =
std::make_unique<CanvasResourceProviderDirectGpuMemoryBuffer>(
size, msaa_sample_count, color_params,
@@ -561,7 +568,7 @@ std::unique_ptr<CanvasResourceProvider> CanvasResourceProvider::Create(
is_origin_top_left);
}
break;
- case kBitmapGpuMemoryBufferResourceType:
+ case CanvasResourceType::kBitmapGpuMemoryBuffer:
if (!SharedGpuContext::IsGpuCompositingEnabled())
continue;
if (presentation_mode != kAllowImageChromiumPresentationMode)
@@ -579,20 +586,20 @@ std::unique_ptr<CanvasResourceProvider> CanvasResourceProvider::Create(
size, color_params, context_provider_wrapper,
resource_dispatcher);
break;
- case kSharedBitmapResourceType:
+ case CanvasResourceType::kSharedBitmap:
if (!resource_dispatcher)
continue;
provider = std::make_unique<CanvasResourceProviderSharedBitmap>(
size, color_params, resource_dispatcher);
break;
- case kTextureResourceType:
+ case CanvasResourceType::kTexture:
if (!context_provider_wrapper)
continue;
provider = std::make_unique<CanvasResourceProviderTexture>(
size, msaa_sample_count, color_params, context_provider_wrapper,
resource_dispatcher, is_origin_top_left);
break;
- case kBitmapResourceType:
+ case CanvasResourceType::kBitmap:
provider = std::make_unique<CanvasResourceProviderBitmap>(
size, color_params, context_provider_wrapper, resource_dispatcher);
break;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc b/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc
index 25fdcaa6f59..9fa1a526ebe 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc
@@ -77,12 +77,12 @@ ColorCorrectionTestUtils::ColorSpaceConversionToSkColorSpace(
if (conversion == kColorSpaceConversion_LinearRGB)
return SkColorSpace::MakeSRGBLinear();
if (conversion == kColorSpaceConversion_P3) {
- return SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma,
- SkColorSpace::kDCIP3_D65_Gamut);
+ return SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear,
+ SkNamedGamut::kDCIP3);
}
if (conversion == kColorSpaceConversion_Rec2020) {
- return SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma,
- SkColorSpace::kRec2020_Gamut);
+ return SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear,
+ SkNamedGamut::kRec2020);
}
return nullptr;
}
@@ -286,9 +286,12 @@ bool ColorCorrectionTestUtils::MatchSkImages(sk_sp<SkImage> src_image,
return false;
// Color type is not checked since the decoded image does not have a specific
// color type, unless it is drawn onto a surface or readPixels() is called.
- if (!MatchColorSpace(src_image->refColorSpace(),
- dst_image->refColorSpace())) {
- return false;
+ // Only compare color spaces if both are non-null
+ if (src_image->refColorSpace() && dst_image->refColorSpace()) {
+ if (!MatchColorSpace(src_image->refColorSpace(),
+ dst_image->refColorSpace())) {
+ return false;
+ }
}
bool test_passed = true;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.h b/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.h
index 4ce10d0025a..f052b58fdd8 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.h
@@ -73,6 +73,9 @@ class ColorCorrectionTestUtils {
static bool MatchColorSpace(sk_sp<SkColorSpace> src_color_space,
sk_sp<SkColorSpace> dst_color_space);
+ // Compares size, colorspace and pixel values of two images
+ // If the colorspace of either image is null the colorspaces are assumed
+ // to be equal
static bool MatchSkImages(sk_sp<SkImage> src_image,
sk_sp<SkImage> dst_image,
unsigned uint8_tolerance,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/README.md b/chromium/third_party/blink/renderer/platform/graphics/compositing/README.md
index 274707ffec5..f8334d739ce 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/README.md
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/README.md
@@ -5,7 +5,7 @@ This directory contains the implementation of the "Blink compositing algorithm".
This code is owned by the [paint team][paint-team-site].
[paint-team-site]: https://www.chromium.org/teams/paint-team
-This document explains the SPv2 world as it develops, not the SPv1 world it
+This document explains the CAP world as it develops, not the SPv1 world it
replaces.
## Blink compositing algorithm
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper_test.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper_test.cc
index a1b314914fd..c9c643ff9ef 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper_test.cc
@@ -37,7 +37,8 @@ class ChunkToLayerMapperTest : public testing::Test {
e0(), EffectPaintPropertyNode::State{
layer_transform_.get(), layer_clip_.get(),
kColorFilterLuminanceToAlpha, CompositorFilterOperations(),
- 0.789f, CompositorFilterOperations(), SkBlendMode::kSrcIn});
+ 0.789f, CompositorFilterOperations(), gfx::RectF(),
+ SkBlendMode::kSrcIn});
}
return PropertyTreeState(layer_transform_.get(), layer_clip_.get(),
layer_effect_.get());
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc
index 374222bd712..dc6ed8d6271 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc
@@ -32,7 +32,9 @@ ContentLayerClientImpl::ContentLayerClientImpl()
cc_picture_layer_->SetLayerClient(weak_ptr_factory_.GetWeakPtr());
}
-ContentLayerClientImpl::~ContentLayerClientImpl() = default;
+ContentLayerClientImpl::~ContentLayerClientImpl() {
+ cc_picture_layer_->ClearClient();
+}
static int GetTransformId(const TransformPaintPropertyNode* transform,
ContentLayerClientImpl::LayerAsJSONContext& context) {
@@ -84,7 +86,7 @@ static int GetTransformId(const TransformPaintPropertyNode* transform,
return transform_id;
}
-// This is the SPv2 version of GraphicsLayer::LayerAsJSONInternal().
+// This is the CAP version of GraphicsLayer::LayerAsJSONInternal().
std::unique_ptr<JSONObject> ContentLayerClientImpl::LayerAsJSON(
LayerAsJSONContext& context) const {
std::unique_ptr<JSONObject> json = JSONObject::Create();
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
index 43aeb50ebdd..4d20e8dc113 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -10,6 +10,7 @@
#include "cc/layers/layer.h"
#include "cc/layers/picture_layer.h"
#include "cc/paint/display_item_list.h"
+#include "cc/trees/effect_node.h"
#include "cc/trees/layer_tree_host.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h"
@@ -67,8 +68,9 @@ PaintArtifactCompositor::PaintArtifactCompositor(
base::RepeatingCallback<void(const gfx::ScrollOffset&,
const cc::ElementId&)> scroll_callback)
: scroll_callback_(std::move(scroll_callback)),
- tracks_raster_invalidations_(false) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled() &&
+ tracks_raster_invalidations_(false),
+ needs_update_(true) {
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled())
return;
root_layer_ = cc::Layer::Create();
@@ -86,6 +88,8 @@ PaintArtifactCompositor::~PaintArtifactCompositor() {
}
void PaintArtifactCompositor::EnableExtraDataForTesting() {
+ if (!extra_data_for_testing_enabled_)
+ SetNeedsUpdate(true);
extra_data_for_testing_enabled_ = true;
extra_data_for_testing_ = std::make_unique<ExtraDataForTesting>();
}
@@ -205,7 +209,7 @@ PaintArtifactCompositor::ScrollHitTestLayerForPendingLayer(
// match (see: crbug.com/753124).
auto bounds = scroll_node.ContainerRect().Size();
// Mark the layer as scrollable.
- // TODO(pdr): When SPV2 launches this parameter for bounds will not be needed.
+ // TODO(pdr): When CAP launches this parameter for bounds will not be needed.
scroll_layer->SetScrollable(static_cast<gfx::Size>(bounds));
// Set the layer's bounds equal to the container because the scroll layer
// does not scroll.
@@ -412,11 +416,13 @@ static bool CanUpcastTo(const PropertyTreeState& guest,
guest.Transform()->IsBackfaceHidden())
return false;
- auto* home_clip = home.Clip()->Unalias();
- for (const ClipPaintPropertyNode* current_clip = guest.Clip()->Unalias();
+ // TODO(crbug.com/923729): Note that SafeUnalias() is a speculative fix for
+ // the referenced bug. The home and guest Clips should always exist, so we can
+ // just call Unalias on them.
+ auto* home_clip = SafeUnalias(home.Clip());
+ for (const ClipPaintPropertyNode* current_clip = SafeUnalias(guest.Clip());
current_clip != home_clip;
- current_clip = current_clip->Parent() ? current_clip->Parent()->Unalias()
- : nullptr) {
+ current_clip = SafeUnalias(current_clip->Parent())) {
if (!current_clip || current_clip->HasDirectCompositingReasons())
return false;
if (!IsNonCompositingAncestorOf(
@@ -518,6 +524,7 @@ static bool SkipGroupIfEffectivelyInvisible(
void PaintArtifactCompositor::LayerizeGroup(
const PaintArtifact& paint_artifact,
+ const Settings& settings,
Vector<PendingLayer>& pending_layers,
const EffectPaintPropertyNode& current_group,
Vector<PaintChunk>::const_iterator& chunk_it) {
@@ -578,8 +585,8 @@ void PaintArtifactCompositor::LayerizeGroup(
// Case C: The following chunks belong to a subgroup. Process them by
// a recursion call.
wtf_size_t first_layer_in_subgroup = pending_layers.size();
- LayerizeGroup(paint_artifact, pending_layers, *unaliased_subgroup,
- chunk_it);
+ LayerizeGroup(paint_artifact, settings, pending_layers,
+ *unaliased_subgroup, chunk_it);
// Now the chunk iterator stepped over the subgroup we just saw.
// If the subgroup generated 2 or more layers then the subgroup must be
// composited to satisfy grouping requirement.
@@ -624,11 +631,12 @@ void PaintArtifactCompositor::LayerizeGroup(
void PaintArtifactCompositor::CollectPendingLayers(
const PaintArtifact& paint_artifact,
+ const Settings& settings,
Vector<PendingLayer>& pending_layers) {
Vector<PaintChunk>::const_iterator cursor =
paint_artifact.PaintChunks().begin();
- LayerizeGroup(paint_artifact, pending_layers, EffectPaintPropertyNode::Root(),
- cursor);
+ LayerizeGroup(paint_artifact, settings, pending_layers,
+ EffectPaintPropertyNode::Root(), cursor);
DCHECK_EQ(paint_artifact.PaintChunks().end(), cursor);
}
@@ -651,6 +659,7 @@ class SynthesizedClip : private cc::ContentLayerClient {
CompositorElementIdFromUniqueObjectId(NewUniqueObjectId());
layer_->SetIsDrawable(true);
}
+ ~SynthesizedClip() override { layer_->ClearClient(); }
void Update(const FloatRoundedRect& rrect,
scoped_refptr<const RefCountedPath> path) {
@@ -749,10 +758,32 @@ cc::Layer* PaintArtifactCompositor::CreateOrReuseSynthesizedClipLayer(
return synthesized_clip.GetLayer();
}
+static void UpdateCompositorViewportProperties(
+ const PaintArtifactCompositor::ViewportProperties& properties,
+ PropertyTreeManager& property_tree_manager,
+ cc::LayerTreeHost* layer_tree_host) {
+ cc::LayerTreeHost::ViewportPropertyIds ids;
+ // This is also needed by pre-CompositeAfterPaint, so is not guarded by
+ // CompositeAfterPaintEnabled().
+ if (properties.page_scale) {
+ ids.page_scale_transform =
+ property_tree_manager.EnsureCompositorPageScaleTransformNode(
+ properties.page_scale);
+ }
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ if (properties.inner_scroll_translation) {
+ ids.inner_scroll = property_tree_manager.EnsureCompositorScrollNode(
+ properties.inner_scroll_translation);
+ }
+ layer_tree_host->RegisterViewportPropertyIds(ids);
+ }
+}
+
void PaintArtifactCompositor::Update(
scoped_refptr<const PaintArtifact> paint_artifact,
CompositorElementIdSet& composited_element_ids,
- TransformPaintPropertyNode* viewport_scale_node) {
+ const ViewportProperties& viewport_properties,
+ const Settings& settings) {
DCHECK(root_layer_);
// The tree will be null after detaching and this update can be ignored.
@@ -761,6 +792,11 @@ void PaintArtifactCompositor::Update(
if (!host)
return;
+ // Skip updating property trees, pushing cc::Layers, and issuing raster
+ // invalidations if possible.
+ if (!NeedsUpdate())
+ return;
+
// When using BlinkGenPropertyTrees, the compositor accepts a list of layers
// and property trees instead of building property trees. This DCHECK ensures
// we have not forgotten to set |use_layer_lists|.
@@ -778,16 +814,10 @@ void PaintArtifactCompositor::Update(
PropertyTreeManager property_tree_manager(
*this, *host->property_trees(), root_layer_.get(), &layer_list_builder);
Vector<PendingLayer, 0> pending_layers;
- CollectPendingLayers(*paint_artifact, pending_layers);
+ CollectPendingLayers(*paint_artifact, settings, pending_layers);
- cc::LayerTreeHost::ViewportPropertyIds viewport_property_ids;
- if (viewport_scale_node) {
- viewport_property_ids.page_scale_transform =
- property_tree_manager.EnsureCompositorPageScaleTransformNode(
- viewport_scale_node);
- }
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- host->RegisterViewportPropertyIds(viewport_property_ids);
+ UpdateCompositorViewportProperties(viewport_properties, property_tree_manager,
+ host);
Vector<std::unique_ptr<ContentLayerClientImpl>> new_content_layer_clients;
new_content_layer_clients.ReserveCapacity(pending_layers.size());
@@ -796,6 +826,8 @@ void PaintArtifactCompositor::Update(
for (auto& entry : synthesized_clip_cache_)
entry.in_use = false;
+ // Clear prior frame ids before inserting new ones.
+ composited_element_ids.clear();
for (auto& pending_layer : pending_layers) {
const auto& property_state = pending_layer.property_tree_state;
const auto* transform = property_state.Transform();
@@ -817,9 +849,9 @@ void PaintArtifactCompositor::Update(
paint_artifact, pending_layer, layer_offset, new_content_layer_clients,
new_scroll_hit_test_layers);
- // Pre-SPV2, touch action rects are updated through
+ // Pre-CompositeAfterPaint, touch action rects are updated through
// ScrollingCoordinator::UpdateLayerTouchActionRects.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
auto paint_chunks = paint_artifact->GetPaintChunkSubset(
pending_layer.paint_chunk_indices);
UpdateTouchActionRects(layer.get(), layer_offset, property_state,
@@ -866,8 +898,10 @@ void PaintArtifactCompositor::Update(
// Calling |PropertyTreeStateChanged| for every pending layer is
// O(|property nodes|^2) and could be optimized by caching the lookup of
// nodes known to be changed/unchanged.
- if (PropertyTreeStateChanged(property_state))
+ if (PropertyTreeStateChanged(property_state)) {
layer->SetSubtreePropertyChanged();
+ root_layer_->SetNeedsCommit();
+ }
}
property_tree_manager.Finalize();
content_layer_clients_.swap(new_content_layer_clients);
@@ -885,15 +919,21 @@ void PaintArtifactCompositor::Update(
}
}
- root_layer_->SetChildLayerList(layer_list_builder.Finalize());
+ // This should be done before UpdateRenderSurfaceForEffects() for which to
+ // get property tree node ids from the layers.
+ host->property_trees()->sequence_number = g_s_property_tree_sequence_number;
+
+ auto layers = layer_list_builder.Finalize();
+ UpdateRenderSurfaceForEffects(*host, layers);
+ root_layer_->SetChildLayerList(std::move(layers));
// Update the host's active registered element ids.
host->SetActiveRegisteredElementIds(composited_element_ids);
// Mark the property trees as having been rebuilt.
- host->property_trees()->sequence_number = g_s_property_tree_sequence_number;
host->property_trees()->needs_rebuild = false;
host->property_trees()->ResetCachedData();
+ SetNeedsUpdate(false);
g_s_property_tree_sequence_number++;
@@ -912,6 +952,33 @@ void PaintArtifactCompositor::Update(
#endif
}
+// Every effect is supposed to have render surface enabled for grouping, but we
+// can omit one if the effect is opacity-only, render surface is not forced,
+// and the effect has only one compositing child. This is both for optimization
+// and not introducing sub-pixel differences in web tests.
+// TODO(crbug.com/504464): There is ongoing work in cc to delay render surface
+// decision until later phase of the pipeline. Remove premature optimization
+// here once the work is ready.
+void PaintArtifactCompositor::UpdateRenderSurfaceForEffects(
+ cc::LayerTreeHost& host,
+ const cc::LayerList& layers) {
+ HashSet<int> pending_render_surfaces;
+ auto& effect_tree = host.property_trees()->effect_tree;
+ for (const auto& layer : layers) {
+ for (auto* effect = effect_tree.Node(layer->effect_tree_index());
+ !effect->has_render_surface;
+ effect = effect_tree.Node(effect->parent_id)) {
+ if (effect->opacity != 1.f &&
+ !pending_render_surfaces.insert(effect->id).is_new_entry) {
+ // The opacity-only effect is seen the second time, which means that it
+ // has more than one compositing child and needs a render surface.
+ effect->has_render_surface = true;
+ break;
+ }
+ }
+ }
+}
+
void LayerListBuilder::Add(scoped_refptr<cc::Layer> layer) {
DCHECK(list_valid_);
list_.push_back(layer);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
index 1b04c0b9d04..26a8f15ebe3 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
@@ -21,6 +21,7 @@
namespace cc {
struct ElementId;
class Layer;
+class LayerTreeHost;
}
namespace gfx {
@@ -53,7 +54,7 @@ class LayerListBuilder {
// changes in the paint artifact.
//
// PaintArtifactCompositor is the successor to PaintLayerCompositor, reflecting
-// the new home of compositing decisions after paint in Slimming Paint v2.
+// the new home of compositing decisions after paint with CompositeAfterPaint.
class PLATFORM_EXPORT PaintArtifactCompositor final
: private PropertyTreeManagerClient {
USING_FAST_MALLOC(PaintArtifactCompositor);
@@ -68,13 +69,25 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
new PaintArtifactCompositor(std::move(scroll_callback)));
}
+ struct ViewportProperties {
+ const TransformPaintPropertyNode* page_scale = nullptr;
+ const TransformPaintPropertyNode* inner_scroll_translation = nullptr;
+ // TODO(crbug.com/909750): Add other viewport properties, e.g.
+ // outer_scroll_translation.
+ };
+
+ struct Settings {
+ bool prefer_compositing_to_lcd_text = false;
+ };
+
// Updates the layer tree to match the provided paint artifact.
//
// Populates |composited_element_ids| with the CompositorElementId of all
// animations for which we saw a paint chunk and created a layer.
void Update(scoped_refptr<const PaintArtifact>,
CompositorElementIdSet& composited_element_ids,
- TransformPaintPropertyNode* viewport_scale_node);
+ const ViewportProperties& viewport_properties,
+ const Settings& settings);
// The root layer of the tree managed by this object.
cc::Layer* RootLayer() const { return root_layer_.get(); }
@@ -119,6 +132,9 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
const PropertyTreeState& layer_state,
const PaintChunkSubset& paint_chunks);
+ void SetNeedsUpdate(bool needs_update) { needs_update_ = needs_update; }
+ bool NeedsUpdate() const { return needs_update_; }
+
private:
// A pending layer is a collection of paint chunks that will end up in
// the same cc::Layer.
@@ -153,7 +169,9 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
// Collects the PaintChunks into groups which will end up in the same
// cc layer. This is the entry point of the layerization algorithm.
void CollectPendingLayers(const PaintArtifact&,
+ const Settings& settings,
Vector<PendingLayer>& pending_layers);
+
// This is the internal recursion of collectPendingLayers. This function
// loops over the list of paint chunks, scoped by an isolated group
// (i.e. effect node). Inside of the loop, chunks are tested for overlap
@@ -172,6 +190,7 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
// overlap with other chunks in the parent group, if grouping requirement
// can be satisfied (and the effect node has no direct reason).
static void LayerizeGroup(const PaintArtifact&,
+ const Settings& settings,
Vector<PendingLayer>& pending_layers,
const EffectPaintPropertyNode&,
Vector<PaintChunk>::const_iterator& chunk_cursor);
@@ -222,11 +241,15 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
CompositorElementId& mask_isolation_id,
CompositorElementId& mask_effect_id) final;
+ static void UpdateRenderSurfaceForEffects(cc::LayerTreeHost&,
+ const cc::LayerList&);
+
// Provides a callback for notifying blink of composited scrolling.
base::RepeatingCallback<void(const gfx::ScrollOffset&, const cc::ElementId&)>
scroll_callback_;
bool tracks_raster_invalidations_;
+ bool needs_update_;
scoped_refptr<cc::Layer> root_layer_;
Vector<std::unique_ptr<ContentLayerClientImpl>> content_layer_clients_;
@@ -242,7 +265,7 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
bool extra_data_for_testing_enabled_ = false;
std::unique_ptr<ExtraDataForTesting> extra_data_for_testing_;
- friend class StubChromeClientForSPv2;
+ friend class StubChromeClientForCAP;
friend class PaintArtifactCompositorTest;
DISALLOW_COPY_AND_ASSIGN(PaintArtifactCompositor);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
index 1855e61bdf5..a601fe254bc 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
@@ -24,6 +24,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h"
+#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
#include "third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.h"
#include "third_party/blink/renderer/platform/testing/fake_display_item_client.h"
@@ -130,18 +131,17 @@ class PaintArtifactCompositorTest : public testing::Test,
Update(artifact, element_ids);
}
- void Update(scoped_refptr<const PaintArtifact> artifact,
- CompositorElementIdSet& element_ids) {
- // Pass nullptr for the visual viewport paint property nodes since we're
- // really just checking the internals of PaintArtifactCompositor.
- Update(artifact, element_ids, nullptr);
- }
+ using ViewportProperties = PaintArtifactCompositor::ViewportProperties;
+ using Settings = PaintArtifactCompositor::Settings;
- void Update(scoped_refptr<const PaintArtifact> artifact,
- CompositorElementIdSet& element_ids,
- TransformPaintPropertyNode* viewport_scale_transform_node) {
+ void Update(
+ scoped_refptr<const PaintArtifact> artifact,
+ CompositorElementIdSet& element_ids,
+ const ViewportProperties& viewport_properties = ViewportProperties(),
+ const Settings& settings = Settings()) {
+ paint_artifact_compositor_->SetNeedsUpdate(true);
paint_artifact_compositor_->Update(artifact, element_ids,
- viewport_scale_transform_node);
+ viewport_properties, settings);
layer_tree_->layer_tree_host()->LayoutAndUpdateLayers();
}
@@ -151,8 +151,8 @@ class PaintArtifactCompositorTest : public testing::Test,
cc::Layer* RootLayer() { return paint_artifact_compositor_->RootLayer(); }
- // SlimmingPaintV2 creates scroll hit test display items (which create scroll
- // hit test layers in PaintArtifactCompositor) whereas in
+ // CompositeAfterPaint creates scroll hit test display items (which create
+ // scroll hit test layers in PaintArtifactCompositor) whereas in
// BlinkGenPropertyTrees, scrollable foreign layers are created in
// ScrollingCoordinator and passed to PaintArtifactCompositor. This function
// is used to create a chunk representing the scrollable layer in either of
@@ -182,8 +182,8 @@ class PaintArtifactCompositorTest : public testing::Test,
.ScrollHitTest(scroll_offset);
}
- // Returns the |num|th scrollable layer. In SlimmingPaintV2, this will be a
- // scroll hit test layer, whereas in BlinkGenPropertyTrees this will be a
+ // Returns the |num|th scrollable layer. In CompositeAfterPaint, this will be
+ // a scroll hit test layer, whereas in BlinkGenPropertyTrees this will be a
// content layer.
cc::Layer* ScrollableLayerAt(size_t num) {
if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
@@ -203,7 +203,7 @@ class PaintArtifactCompositorTest : public testing::Test,
.get();
}
- // Returns the |num|th non-scrollable layer. In SlimmingPaintV2, content
+ // Returns the |num|th non-scrollable layer. In CompositeAfterPaint, content
// layers are not scrollable so this is the |num|th content layer. In
// BlinkGenPropertyTrees, content layers are scrollable and non-scrollable, so
// this will return the |num|th content layer that is not scrollable.
@@ -3254,8 +3254,10 @@ TEST_P(PaintArtifactCompositorTest, CreatesViewportNodes) {
TransformPaintPropertyNode::Root(), std::move(transform_state));
TestPaintArtifact artifact;
+ ViewportProperties viewport_properties;
+ viewport_properties.page_scale = scale_transform_node.get();
CompositorElementIdSet element_ids;
- Update(artifact.Build(), element_ids, scale_transform_node.get());
+ Update(artifact.Build(), element_ids, viewport_properties);
cc::TransformTree& transform_tree = GetPropertyTrees().transform_tree;
cc::TransformNode* cc_transform_node = transform_tree.FindNodeFromElementId(
@@ -3267,4 +3269,169 @@ TEST_P(PaintArtifactCompositorTest, CreatesViewportNodes) {
EXPECT_TRUE(cc_transform_node->pre_local.IsIdentity());
}
+enum { kNoRenderSurface, kHasRenderSurface };
+
+#define EXPECT_OPACITY(effect_id, expected_opacity, expected_render_surface) \
+ do { \
+ const auto* effect = GetPropertyTrees().effect_tree.Node(effect_id); \
+ EXPECT_EQ(expected_opacity, effect->opacity); \
+ EXPECT_EQ(expected_render_surface == kHasRenderSurface, \
+ effect->has_render_surface); \
+ } while (false)
+
+TEST_P(PaintArtifactCompositorTest, OpacityRenderSurfaces) {
+ // e
+ // / | \
+ // a b c -- L4
+ // / \ / \ \
+ // aa ab L2 L3 ca (L = layer)
+ // | | |
+ // L0 L1 L5
+ auto e = CreateOpacityEffect(e0(), 0.1f);
+ auto a = CreateOpacityEffect(*e, 0.2f);
+ auto b =
+ CreateOpacityEffect(*e, 0.3f, CompositingReason::kActiveOpacityAnimation);
+ auto c =
+ CreateOpacityEffect(*e, 0.4f, CompositingReason::kActiveOpacityAnimation);
+ auto aa =
+ CreateOpacityEffect(*a, 0.5f, CompositingReason::kActiveOpacityAnimation);
+ auto ab =
+ CreateOpacityEffect(*a, 0.6f, CompositingReason::kActiveOpacityAnimation);
+ auto ca =
+ CreateOpacityEffect(*c, 0.7f, CompositingReason::kActiveOpacityAnimation);
+ auto t = CreateTransform(t0(), TransformationMatrix().Rotate(90),
+ FloatPoint3D(), CompositingReason::k3DTransform);
+
+ TestPaintArtifact artifact;
+ FloatRect r(150, 150, 100, 100);
+ artifact.Chunk(t0(), c0(), *aa).RectDrawing(r, Color::kWhite);
+ artifact.Chunk(t0(), c0(), *ab).RectDrawing(r, Color::kWhite);
+ artifact.Chunk(t0(), c0(), *b).RectDrawing(r, Color::kWhite);
+ artifact.Chunk(*t, c0(), *b).RectDrawing(r, Color::kWhite);
+ artifact.Chunk(t0(), c0(), *c).RectDrawing(r, Color::kWhite);
+ artifact.Chunk(t0(), c0(), *ca).RectDrawing(r, Color::kWhite);
+ Update(artifact.Build());
+ ASSERT_EQ(6u, ContentLayerCount());
+
+ int effect_ids[6];
+ for (size_t i = 0; i < ContentLayerCount(); i++)
+ effect_ids[i] = ContentLayerAt(i)->effect_tree_index();
+
+ // Effects of layer 0, 1, 5 each has one compositing layer, so don't have
+ // render surface.
+ EXPECT_OPACITY(effect_ids[0], 0.5f, kNoRenderSurface);
+ EXPECT_OPACITY(effect_ids[1], 0.6f, kNoRenderSurface);
+ EXPECT_OPACITY(effect_ids[5], 0.7f, kNoRenderSurface);
+
+ // Layer 2 and 3 have the same effect state. The effect has render surface
+ // because it has two compositing layers.
+ EXPECT_EQ(effect_ids[2], effect_ids[3]);
+ EXPECT_OPACITY(effect_ids[2], 0.3f, kHasRenderSurface);
+
+ // Effect |a| has two indirect compositing layers, so has render surface.
+ const auto& effect_tree = GetPropertyTrees().effect_tree;
+ int id_a = effect_tree.Node(effect_ids[0])->parent_id;
+ EXPECT_EQ(id_a, effect_tree.Node(effect_ids[1])->parent_id);
+ EXPECT_OPACITY(id_a, 0.2f, kHasRenderSurface);
+
+ // Effect |c| has one direct and one indirect compositing layers, so has
+ // render surface.
+ EXPECT_OPACITY(effect_ids[4], 0.4f, kHasRenderSurface);
+
+ // Though all children of effect |e| have render surfaces and |e| doesn't
+ // control any compositing layer, we still give it a render surface for
+ // simplicity of the algorithm.
+ EXPECT_OPACITY(effect_tree.Node(effect_ids[4])->parent_id, 0.1f,
+ kHasRenderSurface);
+}
+
+TEST_P(PaintArtifactCompositorTest, OpacityIndirectlyAffectingTwoLayers) {
+ auto opacity = CreateOpacityEffect(e0(), 0.5f);
+ auto child_composited_effect = CreateOpacityEffect(
+ *opacity, 1.f, CompositingReason::kActiveOpacityAnimation);
+ auto grandchild_composited_effect =
+ CreateOpacityEffect(*child_composited_effect, 1.f,
+ CompositingReason::kActiveOpacityAnimation);
+
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), c0(), *child_composited_effect)
+ .RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite);
+ artifact.Chunk(t0(), c0(), *grandchild_composited_effect)
+ .RectDrawing(FloatRect(150, 150, 100, 100), Color::kGray);
+ Update(artifact.Build());
+ ASSERT_EQ(2u, ContentLayerCount());
+
+ const auto& effect_tree = GetPropertyTrees().effect_tree;
+ int layer0_effect_id = ContentLayerAt(0)->effect_tree_index();
+ EXPECT_OPACITY(layer0_effect_id, 1.f, kNoRenderSurface);
+ int layer1_effect_id = ContentLayerAt(1)->effect_tree_index();
+ EXPECT_OPACITY(layer1_effect_id, 1.f, kNoRenderSurface);
+ int opacity_id = effect_tree.Node(layer0_effect_id)->parent_id;
+ EXPECT_OPACITY(opacity_id, 0.5f, kHasRenderSurface);
+}
+
+TEST_P(PaintArtifactCompositorTest, Non2dAxisAlignedClip) {
+ auto rotate = CreateTransform(t0(), TransformationMatrix().Rotate(45));
+ auto clip = CreateClip(c0(), rotate.get(), FloatRoundedRect(50, 50, 50, 50));
+ auto opacity = CreateOpacityEffect(
+ e0(), 0.5f, CompositingReason::kActiveOpacityAnimation);
+
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), *clip, *opacity)
+ .RectDrawing(FloatRect(50, 50, 50, 50), Color::kWhite);
+ Update(artifact.Build());
+ ASSERT_EQ(1u, ContentLayerCount());
+
+ // We should create a synthetic effect node for the non-2d-axis-aligned clip.
+ int clip_id = ContentLayerAt(0)->clip_tree_index();
+ const auto* cc_clip = GetPropertyTrees().clip_tree.Node(clip_id);
+ int effect_id = ContentLayerAt(0)->effect_tree_index();
+ const auto* cc_effect = GetPropertyTrees().effect_tree.Node(effect_id);
+ EXPECT_OPACITY(effect_id, 1.f, kHasRenderSurface);
+ EXPECT_OPACITY(cc_effect->parent_id, 0.5f, kNoRenderSurface);
+ EXPECT_EQ(cc_effect->clip_id, cc_clip->parent_id);
+}
+
+TEST_P(PaintArtifactCompositorTest,
+ Non2dAxisAlignedClipUnderLaterRenderSurface) {
+ auto rotate1 =
+ CreateTransform(t0(), TransformationMatrix().Rotate(45), FloatPoint3D(),
+ CompositingReason::k3DTransform);
+ auto rotate2 =
+ CreateTransform(*rotate1, TransformationMatrix().Rotate(-45),
+ FloatPoint3D(), CompositingReason::k3DTransform);
+ auto clip = CreateClip(c0(), rotate2.get(), FloatRoundedRect(50, 50, 50, 50));
+ auto opacity =
+ CreateOpacityEffect(e0(), rotate1.get(), &c0(), 0.5f,
+ CompositingReason::kActiveOpacityAnimation);
+
+ // This assert ensures the test actually tests the situation. If it fails
+ // due to floating-point errors, we should choose other transformation values
+ // to make it succeed.
+ ASSERT_TRUE(
+ GeometryMapper::SourceToDestinationProjection(&t0(), rotate2.get())
+ .Preserves2dAxisAlignment());
+
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), c0(), *opacity)
+ .RectDrawing(FloatRect(50, 50, 50, 50), Color::kWhite);
+ artifact.Chunk(*rotate1, c0(), *opacity)
+ .RectDrawing(FloatRect(50, 50, 50, 50), Color::kWhite);
+ artifact.Chunk(*rotate2, *clip, *opacity)
+ .RectDrawing(FloatRect(50, 50, 50, 50), Color::kWhite);
+ Update(artifact.Build());
+ ASSERT_EQ(3u, ContentLayerCount());
+
+ // We should create a synthetic effect node for the non-2d-axis-aligned clip,
+ // though the accumulated transform to the known render surface was identity
+ // when the cc clip node was created.
+ int clip_id = ContentLayerAt(2)->clip_tree_index();
+ const auto* cc_clip = GetPropertyTrees().clip_tree.Node(clip_id);
+ int effect_id = ContentLayerAt(2)->effect_tree_index();
+ const auto* cc_effect = GetPropertyTrees().effect_tree.Node(effect_id);
+ EXPECT_OPACITY(effect_id, 1.f, kHasRenderSurface);
+ EXPECT_OPACITY(cc_effect->parent_id, 0.5f, kHasRenderSurface);
+ EXPECT_EQ(cc_effect->clip_id, cc_clip->parent_id);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
index c14f863846a..9982f86778c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
@@ -341,8 +341,8 @@ void ConversionContext::SwitchToClip(const ClipPaintPropertyNode* target_clip) {
#endif
// This bug is known to happen in SPv1 due to some clip-escaping corner
// cases that are very difficult to fix in legacy architecture.
- // In SPv2 this should never happen.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
+ // In CAP this should never happen.
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
NOTREACHED();
break;
}
@@ -515,9 +515,7 @@ void ConversionContext::StartEffect(const EffectPaintPropertyNode* effect) {
effect->GetColorFilter()));
save_layer_id = cc_list_.push<cc::SaveLayerOp>(nullptr, &flags);
} else {
- constexpr bool preserve_lcd_text_requests = false;
- save_layer_id = cc_list_.push<cc::SaveLayerAlphaOp>(
- nullptr, alpha, preserve_lcd_text_requests);
+ save_layer_id = cc_list_.push<cc::SaveLayerAlphaOp>(nullptr, alpha);
}
saved_count++;
} else {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc
index 6bfb15050c0..eeaae7ecc63 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc
@@ -51,9 +51,9 @@ namespace blink {
namespace {
class PaintChunksToCcLayerTest : public testing::Test,
- private ScopedSlimmingPaintV2ForTest {
+ private ScopedCompositeAfterPaintForTest {
protected:
- PaintChunksToCcLayerTest() : ScopedSlimmingPaintV2ForTest(true) {}
+ PaintChunksToCcLayerTest() : ScopedCompositeAfterPaintForTest(true) {}
};
// Matches PaintOpTypes in a PaintRecord.
@@ -1190,7 +1190,7 @@ TEST_F(PaintChunksToCcLayerTest, StartWithAliasClip) {
// release builds. A DCHECK'd build will trap instead.
#if !DCHECK_IS_ON()
TEST_F(PaintChunksToCcLayerTest, SPv1ChunkEscapeLayerClipFailSafe) {
- ScopedSlimmingPaintV2ForTest spv2_disabler(false);
+ ScopedCompositeAfterPaintForTest cap_disabler(false);
// This test verifies the fail-safe path correctly recovers from a malformed
// chunk that escaped its layer's clip.
FloatRoundedRect clip_rect(0.f, 0.f, 1.f, 1.f);
@@ -1210,7 +1210,7 @@ TEST_F(PaintChunksToCcLayerTest, SPv1ChunkEscapeLayerClipFailSafe) {
}
TEST_F(PaintChunksToCcLayerTest, SPv1ChunkEscapeEffectClipFailSafe) {
- ScopedSlimmingPaintV2ForTest spv2_disabler(false);
+ ScopedCompositeAfterPaintForTest cap_disabler(false);
// This test verifies the fail-safe path correctly recovers from a malformed
// chunk that escaped its effect's clip.
FloatRoundedRect clip_rect(0.f, 0.f, 1.f, 1.f);
@@ -1234,7 +1234,7 @@ TEST_F(PaintChunksToCcLayerTest, SPv1ChunkEscapeEffectClipFailSafe) {
}
TEST_F(PaintChunksToCcLayerTest, SPv1ChunkEscapeLayerClipDoubleFault) {
- ScopedSlimmingPaintV2ForTest spv2_disabler(false);
+ ScopedCompositeAfterPaintForTest cap_disabler(false);
// This test verifies the fail-safe path correctly recovers from a series of
// malformed chunks that escaped their layer's clip.
FloatRoundedRect clip_rect(0.f, 0.f, 1.f, 1.f);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
index 83635ef9c2a..c521cf05576 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
@@ -32,6 +32,12 @@ static constexpr int kSecondaryRootNodeId = 1;
} // namespace
+inline const TransformPaintPropertyNode*
+PropertyTreeManager::EffectState::Transform() const {
+ return effect_type == CcEffectType::kEffect ? effect->LocalTransformSpace()
+ : clip->LocalTransformSpace();
+}
+
PropertyTreeManager::PropertyTreeManager(PropertyTreeManagerClient& client,
cc::PropertyTrees& property_trees,
cc::Layer* root_layer,
@@ -154,26 +160,39 @@ void PropertyTreeManager::SetupRootScrollNode() {
root_layer_->SetScrollTreeIndex(scroll_node.id);
}
+static bool TransformsAre2dAxisAligned(const TransformPaintPropertyNode* a,
+ const TransformPaintPropertyNode* b) {
+ return a == b || GeometryMapper::SourceToDestinationProjection(a, b)
+ .Preserves2dAxisAlignment();
+}
+
void PropertyTreeManager::SetCurrentEffectState(
const cc::EffectNode& cc_effect_node,
CcEffectType effect_type,
const EffectPaintPropertyNode* effect,
const ClipPaintPropertyNode* clip) {
+ const auto* previous_transform =
+ effect->IsRoot() ? nullptr : current_.Transform();
current_.effect_id = cc_effect_node.id;
current_.effect_type = effect_type;
DCHECK(!effect->IsParentAlias() || !effect->Parent());
current_.effect = effect;
DCHECK(!clip->IsParentAlias() || !clip->Parent());
current_.clip = clip;
- if (cc_effect_node.has_render_surface)
- current_.render_surface_transform = effect->LocalTransformSpace();
+
+ if (cc_effect_node.has_render_surface) {
+ current_.may_be_2d_axis_misaligned_to_render_surface = false;
+ } else if (previous_transform &&
+ !current_.may_be_2d_axis_misaligned_to_render_surface) {
+ current_.may_be_2d_axis_misaligned_to_render_surface =
+ !TransformsAre2dAxisAligned(current_.Transform(), previous_transform);
+ }
}
// TODO(crbug.com/504464): Remove this when move render surface decision logic
// into cc compositor thread.
void PropertyTreeManager::SetCurrentEffectHasRenderSurface() {
GetEffectTree().Node(current_.effect_id)->has_render_surface = true;
- current_.render_surface_transform = current_.effect->LocalTransformSpace();
}
int PropertyTreeManager::EnsureCompositorTransformNode(
@@ -458,12 +477,6 @@ void PropertyTreeManager::CloseCcEffect() {
}
}
-static bool TransformsAre2dAxisAligned(const TransformPaintPropertyNode* a,
- const TransformPaintPropertyNode* b) {
- return a == b || GeometryMapper::SourceToDestinationProjection(a, b)
- .Preserves2dAxisAlignment();
-}
-
int PropertyTreeManager::SwitchToEffectNodeWithSynthesizedClip(
const EffectPaintPropertyNode& next_effect,
const ClipPaintPropertyNode& next_clip) {
@@ -519,9 +532,8 @@ int PropertyTreeManager::SwitchToEffectNodeWithSynthesizedClip(
while (current_.effect != &ancestor)
CloseCcEffect();
- bool newly_built = BuildEffectNodesRecursively(&next_effect);
- SynthesizeCcEffectsForClipsIfNeeded(&next_clip, SkBlendMode::kSrcOver,
- newly_built);
+ BuildEffectNodesRecursively(&next_effect);
+ SynthesizeCcEffectsForClipsIfNeeded(&next_clip, SkBlendMode::kSrcOver);
return current_.effect_id;
}
@@ -549,8 +561,9 @@ PropertyTreeManager::NeedsSyntheticEffect(
// Cc requires that a rectangluar clip is 2d-axis-aligned with the render
// surface to correctly apply the clip.
- if (!TransformsAre2dAxisAligned(clip.LocalTransformSpace(),
- current_.render_surface_transform))
+ if (current_.may_be_2d_axis_misaligned_to_render_surface ||
+ !TransformsAre2dAxisAligned(clip.LocalTransformSpace(),
+ current_.Transform()))
return CcEffectType::kSyntheticFor2dAxisAlignment;
return base::nullopt;
@@ -558,8 +571,7 @@ PropertyTreeManager::NeedsSyntheticEffect(
SkBlendMode PropertyTreeManager::SynthesizeCcEffectsForClipsIfNeeded(
const ClipPaintPropertyNode* target_clip,
- SkBlendMode delegated_blend,
- bool effect_is_newly_built) {
+ SkBlendMode delegated_blend) {
auto* unaliased_target_clip = target_clip->Unalias();
if (delegated_blend != SkBlendMode::kSrcOver) {
// Exit all synthetic effect node if the next child has exotic blending mode
@@ -585,16 +597,6 @@ SkBlendMode PropertyTreeManager::SynthesizeCcEffectsForClipsIfNeeded(
if (IsNodeOnAncestorChain(lca, *pre_exit_clip, *current_.clip))
break;
}
-
- // If the effect is an existing node, i.e. already has at least one paint
- // chunk or child effect, and by reaching here it implies we are going to
- // attach either another paint chunk or child effect to it. We can no longer
- // omit render surface for it even for opacity-only node.
- // See comments in PropertyTreeManager::BuildEffectNodesRecursively().
- // TODO(crbug.com/504464): Remove premature optimization here.
- if (!effect_is_newly_built && !IsCurrentCcEffectSynthetic() &&
- current_.effect->Opacity() != 1.f)
- SetCurrentEffectHasRenderSurface();
}
DCHECK(current_.clip->IsAncestorOf(*unaliased_target_clip));
@@ -649,21 +651,19 @@ SkBlendMode PropertyTreeManager::SynthesizeCcEffectsForClipsIfNeeded(
effect_stack_.emplace_back(current_);
SetCurrentEffectState(synthetic_effect, pending_clip.type, current_.effect,
pending_clip.clip);
- current_.render_surface_transform =
- pending_clip.clip->LocalTransformSpace();
}
return delegated_blend;
}
-bool PropertyTreeManager::BuildEffectNodesRecursively(
+void PropertyTreeManager::BuildEffectNodesRecursively(
const EffectPaintPropertyNode* next_effect) {
next_effect = SafeUnalias(next_effect);
if (next_effect == current_.effect)
- return false;
+ return;
DCHECK(next_effect);
- bool newly_built = BuildEffectNodesRecursively(next_effect->Parent());
+ BuildEffectNodesRecursively(next_effect->Parent());
DCHECK_EQ(next_effect->Parent()->Unalias(), current_.effect);
#if DCHECK_IS_ON()
@@ -678,16 +678,15 @@ bool PropertyTreeManager::BuildEffectNodesRecursively(
const auto* output_clip = SafeUnalias(next_effect->OutputClip());
if (output_clip) {
used_blend_mode = SynthesizeCcEffectsForClipsIfNeeded(
- output_clip, next_effect->BlendMode(), newly_built);
+ output_clip, next_effect->BlendMode());
output_clip_id = EnsureCompositorClipNode(output_clip);
} else {
while (IsCurrentCcEffectSynthetic())
CloseCcEffect();
// An effect node can't omit render surface if it has child with exotic
- // blending mode, nor being opacity-only node with more than one child.
+ // blending mode.
// TODO(crbug.com/504464): Remove premature optimization here.
- if (next_effect->BlendMode() != SkBlendMode::kSrcOver ||
- (!newly_built && current_.effect->Opacity() != 1.f))
+ if (next_effect->BlendMode() != SkBlendMode::kSrcOver)
SetCurrentEffectHasRenderSurface();
used_blend_mode = next_effect->BlendMode();
@@ -701,16 +700,10 @@ bool PropertyTreeManager::BuildEffectNodesRecursively(
effect_node.stable_id =
next_effect->GetCompositorElementId().GetInternalValue();
effect_node.clip_id = output_clip_id;
- // Every effect is supposed to have render surface enabled for grouping,
- // but we can get away without one if the effect is opacity-only and has only
- // one compositing child with kSrcOver blend mode. This is both for
- // optimization and not introducing sub-pixel differences in layout tests.
- // See PropertyTreeManager::switchToEffectNode() and above where we
- // retrospectively enable render surface when more than one compositing child
- // or a child with exotic blend mode is detected.
- // TODO(crbug.com/504464): There is ongoing work in cc to delay render surface
- // decision until later phase of the pipeline. Remove premature optimization
- // here once the work is ready.
+
+ // An effect with filters, backdrop filters or non-kSrcOver blend mode needs
+ // a render surface. The render surface status of opacity-only effects will be
+ // updated in PaintArtifactCompositor::UpdateRenderSurfaceForEffects().
if (!next_effect->Filter().IsEmpty() ||
!next_effect->BackdropFilter().IsEmpty() ||
used_blend_mode != SkBlendMode::kSrcOver)
@@ -730,6 +723,7 @@ bool PropertyTreeManager::BuildEffectNodesRecursively(
effect_node.filters = next_effect->Filter().AsCcFilterOperations();
effect_node.backdrop_filters =
next_effect->BackdropFilter().AsCcFilterOperations();
+ effect_node.backdrop_filter_bounds = next_effect->BackdropFilterBounds();
effect_node.filters_origin = next_effect->FiltersOrigin();
effect_node.transform_id =
EnsureCompositorTransformNode(next_effect->LocalTransformSpace());
@@ -749,8 +743,6 @@ bool PropertyTreeManager::BuildEffectNodesRecursively(
effect_stack_.emplace_back(current_);
SetCurrentEffectState(effect_node, CcEffectType::kEffect, next_effect,
output_clip);
-
- return true;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h b/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h
index 1bab20eea08..231b0411e19 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h
@@ -119,11 +119,10 @@ class PropertyTreeManager {
void Finalize();
private:
- bool BuildEffectNodesRecursively(const EffectPaintPropertyNode* next_effect);
+ void BuildEffectNodesRecursively(const EffectPaintPropertyNode* next_effect);
SkBlendMode SynthesizeCcEffectsForClipsIfNeeded(
const ClipPaintPropertyNode* target_clip,
- SkBlendMode delegated_blend,
- bool effect_is_newly_built);
+ SkBlendMode delegated_blend);
void EmitClipMaskLayer();
void CloseCcEffect();
@@ -192,19 +191,34 @@ class PropertyTreeManager {
// effect and clip state from the last
// SwitchToEffectNodeWithSynthesizedClip.
int effect_id;
+
CcEffectType effect_type;
+
// The effect state of the cc effect node.
const EffectPaintPropertyNode* effect;
+
// The clip state of the cc effect node. This value may be shallower than
// the one passed into SwitchToEffectNodeWithSynthesizedClip because not
- // every clip needs to be synthesized as cc effect.
- // Is set to output clip of the effect if the type is kEffect, or set to the
- // synthesized clip node if the type is kSyntheticForNonTrivialClip.
+ // every clip needs to be synthesized as cc effect. Is set to output clip of
+ // the effect if the type is kEffect, or set to the synthesized clip node.
const ClipPaintPropertyNode* clip;
- // The transform space of the containing render surface.
- // TODO(crbug.com/504464): Remove this when move render surface decision
- // logic into cc compositor thread.
- const TransformPaintPropertyNode* render_surface_transform;
+
+ // Whether the transform space of this state may be 2d axis misaligned to
+ // the containing render surface. As there may be new render surfaces
+ // created between this state and the current known ancestor render surface
+ // after this state is created, we must conservatively accumulate this flag
+ // from the known render surface instead of checking if the combined
+ // transform is 2d axis aligned, in case of:
+ // Effect1 (Current known render surface)
+ // Rotate(45deg)
+ // Effect2 (Not known now, but may become render surface later)
+ // Rotate(-45deg)
+ // Clip (Would be mistakenly treated as 2d axis aligned if we used
+ // accumulated transform from the clip to the known render surface.)
+ bool may_be_2d_axis_misaligned_to_render_surface;
+
+ // The transform space of the state.
+ const TransformPaintPropertyNode* Transform() const;
};
// The current effect state. Virtually it's the top of the effect stack if
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h b/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h
index a9d700afff1..39a0bcff494 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h
@@ -135,8 +135,7 @@ class PLATFORM_EXPORT CompositingReason {
kTransformWithCompositedDescendants | kIsolateCompositedDescendants |
kOpacityWithCompositedDescendants | kMaskWithCompositedDescendants |
kFilterWithCompositedDescendants | kBlendingWithCompositedDescendants |
- kReflectionWithCompositedDescendants | kClipsCompositingDescendants |
- kPositionFixedOrStickyWithCompositedDescendants,
+ kReflectionWithCompositedDescendants | kClipsCompositingDescendants,
kCombo3DDescendants =
kPreserve3DWith3DDescendants | kPerspectiveWith3DDescendants,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_client.cc b/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_client.cc
index 434c15b3333..ea742ddd65e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_client.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_client.cc
@@ -26,7 +26,9 @@ CompositorMutatorClient::~CompositorMutatorClient() {
void CompositorMutatorClient::Mutate(
std::unique_ptr<cc::MutatorInputState> input_state) {
TRACE_EVENT0("cc", "CompositorMutatorClient::Mutate");
- mutator_->Mutate(std::move(input_state));
+ // TODO(http://crbug.com/791280): Switch to asynchronous once plumbing is
+ // complete.
+ mutator_->MutateSynchronously(std::move(input_state));
}
void CompositorMutatorClient::SetMutationUpdate(
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_client.h b/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_client.h
index 8823cf44e02..b6fb0b07ccf 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_client.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_client.h
@@ -21,7 +21,11 @@ class PLATFORM_EXPORT CompositorMutatorClient : public cc::LayerTreeMutator,
std::unique_ptr<AnimationWorkletMutatorDispatcherImpl>);
~CompositorMutatorClient() override;
+ void SynchronizeAnimatorName(const String& animator_name) override {}
void SetMutationUpdate(std::unique_ptr<cc::MutatorOutputState>) override;
+ // TODO(http://crbug.com/791280): Plumb notifications through to cc scheduler.
+ void NotifyAnimationsPending() override {}
+ void NotifyAnimationsReady() override {}
// cc::LayerTreeMutator
void SetClient(cc::LayerTreeMutatorClient*) override;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.cc b/chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.cc
index 45501625ff7..59c68f69182 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.cc
@@ -63,7 +63,6 @@ void CrossfadeGeneratedImage::DrawCrossfade(cc::PaintCanvas* canvas,
PaintFlags image_flags(flags);
image_flags.setBlendMode(SkBlendMode::kSrcOver);
image_flags.setColor(ScaleAlpha(flags.getColor(), 1 - percentage_));
- image_flags.setAntiAlias(flags.isAntiAlias());
// TODO(junov): This code should probably be propagating the
// RespectImageOrientationEnum from CrossfadeGeneratedImage::draw(). Code was
// written this way during refactoring to avoid modifying existing behavior,
@@ -106,7 +105,6 @@ void CrossfadeGeneratedImage::DrawTile(GraphicsContext& context,
PaintFlags flags = context.FillFlags();
flags.setBlendMode(SkBlendMode::kSrcOver);
- flags.setAntiAlias(context.ShouldAntialias());
FloatRect dest_rect((FloatPoint()), crossfade_size_);
flags.setFilterQuality(
context.ComputeFilterQuality(this, dest_rect, src_rect));
diff --git a/chromium/third_party/blink/renderer/platform/graphics/draw_looper_builder.cc b/chromium/third_party/blink/renderer/platform/graphics/draw_looper_builder.cc
index ca469f07a27..edb90d9d9fa 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/draw_looper_builder.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/draw_looper_builder.cc
@@ -91,7 +91,7 @@ void DrawLooperBuilder::AddShadow(const FloatSize& offset,
SkPaint* paint = sk_draw_looper_builder_.addLayerOnTop(info);
if (blur) {
- const SkScalar sigma = SkBlurRadiusToSigma(blur);
+ const auto sigma = BlurRadiusToStdDev(blur);
const bool respectCTM = shadow_transform_mode != kShadowIgnoresTransforms;
paint->setMaskFilter(
SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, sigma, respectCTM));
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.cc
index af4e32d69d9..6a33e1fded7 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.cc
@@ -25,7 +25,10 @@
#include "third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.h"
#include <algorithm>
+
#include "SkTableColorFilter.h"
+
+#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/text_stream.h"
@@ -161,7 +164,7 @@ void FEComponentTransfer::GetValues(unsigned char r_values[256],
for (unsigned channel = 0; channel < 4; channel++) {
SECURITY_DCHECK(static_cast<size_t>(transfer_function[channel].type) <
- arraysize(call_effect));
+ base::size(call_effect));
(*call_effect[transfer_function[channel].type])(tables[channel],
transfer_function[channel]);
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc
index 2fdde120800..655e3765a3d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc
@@ -31,7 +31,9 @@
#include "third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h"
#include <memory>
+
#include "base/memory/scoped_refptr.h"
+#include "base/stl_util.h"
#include "components/viz/common/resources/single_release_callback.h"
#include "components/viz/common/resources/transferable_resource.h"
#include "components/viz/test/test_gpu_memory_buffer_manager.h"
@@ -635,7 +637,7 @@ TEST(DrawingBufferDepthStencilTest, packedDepthStencilSupported) {
DepthStencilTestCase(true, true, 1, "both"),
};
- for (size_t i = 0; i < arraysize(cases); i++) {
+ for (size_t i = 0; i < base::size(cases); i++) {
SCOPED_TRACE(cases[i].test_case_name);
auto gl = std::make_unique<DepthStencilTrackingGLES2Interface>();
DepthStencilTrackingGLES2Interface* tracking_gl = gl.get();
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
index 10ff62ac177..1fc321b4251 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
@@ -155,8 +155,9 @@ bool ImageLayerBridge::PrepareTransferableResource(
*out_resource = viz::TransferableResource::MakeSoftware(
registered.bitmap->id(), size, resource_format);
if (RuntimeEnabledFeatures::CanvasColorManagementEnabled()) {
- out_resource->color_space =
- SkColorSpaceToGfxColorSpace(sk_image->refColorSpace());
+ out_resource->color_space = sk_image->colorSpace()
+ ? gfx::ColorSpace(*sk_image->colorSpace())
+ : gfx::ColorSpace::CreateSRGB();
}
auto func = WTF::Bind(&ImageLayerBridge::ResourceReleasedSoftware,
WrapWeakPersistent(this), std::move(registered));
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc
index 6ad59bb2a61..2cc0ad8cc63 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc
@@ -2721,8 +2721,8 @@ GLenum WebGLImageConversion::ComputeImageSizeInBytes(
}
unsigned padding = 0;
- base::CheckedNumeric<uint32_t> checked_residual =
- checked_value % params.alignment;
+ base::CheckedNumeric<uint32_t> checked_residual = checked_value;
+ checked_residual %= static_cast<uint32_t>(params.alignment);
if (!checked_residual.IsValid()) {
return GL_INVALID_VALUE;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc
index a0ace7b10a9..158ee960343 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc
@@ -130,15 +130,20 @@ void XRFrameTransport::FrameSubmit(
// for some out-of-memory situations.
// TODO(billorr): Consider whether we should just drop the frame or exit
// presentation.
- if (gpu_memory_buffer) {
- // We decompose the cloned handle, and use it to create a
- // mojo::ScopedHandle which will own cleanup of the handle, and will be
- // passed over IPC.
- gfx::GpuMemoryBufferHandle gpu_handle = gpu_memory_buffer->CloneHandle();
- vr_presentation_provider->SubmitFrameWithTextureHandle(
- vr_frame_id,
- mojo::WrapPlatformFile(gpu_handle.dxgi_handle.GetHandle()));
+ if (!gpu_memory_buffer) {
+ FrameSubmitMissing(vr_presentation_provider, gl, vr_frame_id);
+ // We didn't actually submit anything, so don't set
+ // the waiting_for_previous_frame_transfer_ and related state.
+ return;
}
+
+ // We decompose the cloned handle, and use it to create a
+ // mojo::ScopedHandle which will own cleanup of the handle, and will be
+ // passed over IPC.
+ gfx::GpuMemoryBufferHandle gpu_handle = gpu_memory_buffer->CloneHandle();
+ vr_presentation_provider->SubmitFrameWithTextureHandle(
+ vr_frame_id,
+ mojo::WrapPlatformFile(gpu_handle.dxgi_handle.GetHandle()));
#else
NOTIMPLEMENTED();
#endif
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc
index ab0754787ba..d866b64127c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc
@@ -42,8 +42,7 @@ scoped_refptr<XRWebGLDrawingBuffer> XRWebGLDrawingBuffer::Create(
bool want_alpha_channel,
bool want_depth_buffer,
bool want_stencil_buffer,
- bool want_antialiasing,
- bool want_multiview) {
+ bool want_antialiasing) {
DCHECK(drawing_buffer);
// Don't proceeed if the context is already lost.
@@ -83,16 +82,11 @@ scoped_refptr<XRWebGLDrawingBuffer> XRWebGLDrawingBuffer::Create(
if (discard_framebuffer_supported)
extensions_util->EnsureExtensionEnabled("GL_EXT_discard_framebuffer");
- // TODO(bajones): Support multiview.
- bool multiview_supported = false;
-
scoped_refptr<XRWebGLDrawingBuffer> xr_drawing_buffer =
base::AdoptRef(new XRWebGLDrawingBuffer(
drawing_buffer, framebuffer, discard_framebuffer_supported,
- want_alpha_channel, want_depth_buffer, want_stencil_buffer,
- multiview_supported));
- if (!xr_drawing_buffer->Initialize(size, multisample_supported,
- multiview_supported)) {
+ want_alpha_channel, want_depth_buffer, want_stencil_buffer));
+ if (!xr_drawing_buffer->Initialize(size, multisample_supported)) {
DLOG(ERROR) << "XRWebGLDrawingBuffer Initialization Failed";
return nullptr;
}
@@ -100,22 +94,83 @@ scoped_refptr<XRWebGLDrawingBuffer> XRWebGLDrawingBuffer::Create(
return xr_drawing_buffer;
}
+void XRWebGLDrawingBuffer::MirrorClient::OnMirrorImageAvailable(
+ scoped_refptr<StaticBitmapImage> image,
+ std::unique_ptr<viz::SingleReleaseCallback> callback) {
+ // Replace the next image if we have one already.
+ if (next_image_ && next_release_callback_) {
+ next_release_callback_->Run(gpu::SyncToken(), false);
+ }
+
+ // Set our new image.
+ next_image_ = image;
+ next_release_callback_ = std::move(callback);
+}
+
+void XRWebGLDrawingBuffer::MirrorClient::BeginDestruction() {
+ // Call all callbacks we have to clean up associated resources. For
+ // next_release_callback_, we report the previous image as "not lost", meaning
+ // we can reuse the texture/image. For previous_release_callback_
+ // and current_release_callback_, we report the image as lost, because we
+ // don't know if the consumer is still using them, so they should not be
+ // reused.
+ if (previous_release_callback_) {
+ previous_release_callback_->Run(gpu::SyncToken(), true);
+ previous_release_callback_ = nullptr;
+ }
+
+ if (current_release_callback_) {
+ current_release_callback_->Run(gpu::SyncToken(), true);
+ current_release_callback_ = nullptr;
+ }
+
+ if (next_release_callback_) {
+ next_release_callback_->Run(gpu::SyncToken(), false);
+ next_release_callback_ = nullptr;
+ }
+
+ next_image_ = nullptr;
+}
+
+scoped_refptr<StaticBitmapImage>
+XRWebGLDrawingBuffer::MirrorClient::GetLastImage() {
+ if (!next_image_)
+ return nullptr;
+
+ scoped_refptr<StaticBitmapImage> ret = next_image_;
+ next_image_ = nullptr;
+ DCHECK(!previous_release_callback_);
+ previous_release_callback_ = std::move(current_release_callback_);
+ DCHECK(!current_release_callback_);
+ current_release_callback_ = std::move(next_release_callback_);
+ return ret;
+}
+
+void XRWebGLDrawingBuffer::MirrorClient::CallLastReleaseCallback() {
+ if (previous_release_callback_)
+ previous_release_callback_->Run(gpu::SyncToken(), false);
+ previous_release_callback_ = nullptr;
+}
+
+XRWebGLDrawingBuffer::MirrorClient::~MirrorClient() {
+ BeginDestruction();
+}
+
XRWebGLDrawingBuffer::XRWebGLDrawingBuffer(DrawingBuffer* drawing_buffer,
GLuint framebuffer,
bool discard_framebuffer_supported,
bool want_alpha_channel,
bool want_depth_buffer,
- bool want_stencil_buffer,
- bool multiview_supported)
+ bool want_stencil_buffer)
: drawing_buffer_(drawing_buffer),
framebuffer_(framebuffer),
discard_framebuffer_supported_(discard_framebuffer_supported),
depth_(want_depth_buffer),
stencil_(want_stencil_buffer),
- alpha_(want_alpha_channel),
- multiview_(false) {}
+ alpha_(want_alpha_channel) {}
void XRWebGLDrawingBuffer::BeginDestruction() {
+ mirror_client_ = nullptr;
back_color_buffer_ = nullptr;
front_color_buffer_ = nullptr;
recycled_color_buffer_queue_.clear();
@@ -124,8 +179,7 @@ void XRWebGLDrawingBuffer::BeginDestruction() {
// TODO(bajones): The GL resources allocated in this function are leaking. Add
// a way to clean up the buffers when the layer is GCed or the session ends.
bool XRWebGLDrawingBuffer::Initialize(const IntSize& size,
- bool use_multisampling,
- bool use_multiview) {
+ bool use_multisampling) {
gpu::gles2::GLES2Interface* gl = drawing_buffer_->ContextGL();
std::unique_ptr<Extensions3DUtil> extensions_util =
@@ -179,7 +233,7 @@ gpu::gles2::GLES2Interface* XRWebGLDrawingBuffer::ContextGL() {
return drawing_buffer_->ContextGL();
}
-void XRWebGLDrawingBuffer::SetMirrorClient(MirrorClient* client) {
+void XRWebGLDrawingBuffer::SetMirrorClient(scoped_refptr<MirrorClient> client) {
mirror_client_ = client;
if (mirror_client_) {
// Immediately send a black 1x1 image to the mirror client to ensure that
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h
index 919566a74f6..157ce76910d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h
@@ -29,8 +29,7 @@ class PLATFORM_EXPORT XRWebGLDrawingBuffer
bool want_alpha_channel,
bool want_depth_buffer,
bool want_stencil_buffer,
- bool want_antialiasing,
- bool want_multiview);
+ bool want_antialiasing);
gpu::gles2::GLES2Interface* ContextGL();
bool ContextLost();
@@ -41,7 +40,6 @@ class PLATFORM_EXPORT XRWebGLDrawingBuffer
bool depth() const { return depth_; }
bool stencil() const { return stencil_; }
bool alpha() const { return alpha_; }
- bool multiview() const { return multiview_; }
void Resize(const IntSize&);
@@ -51,14 +49,25 @@ class PLATFORM_EXPORT XRWebGLDrawingBuffer
scoped_refptr<StaticBitmapImage> TransferToStaticBitmapImage(
std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback);
- class MirrorClient {
+ class PLATFORM_EXPORT MirrorClient : public RefCounted<MirrorClient> {
public:
- virtual void OnMirrorImageAvailable(
- scoped_refptr<StaticBitmapImage>,
- std::unique_ptr<viz::SingleReleaseCallback>) = 0;
+ void OnMirrorImageAvailable(scoped_refptr<StaticBitmapImage>,
+ std::unique_ptr<viz::SingleReleaseCallback>);
+
+ void BeginDestruction();
+ scoped_refptr<StaticBitmapImage> GetLastImage();
+ void CallLastReleaseCallback();
+
+ ~MirrorClient();
+
+ private:
+ scoped_refptr<StaticBitmapImage> next_image_;
+ std::unique_ptr<viz::SingleReleaseCallback> next_release_callback_;
+ std::unique_ptr<viz::SingleReleaseCallback> current_release_callback_;
+ std::unique_ptr<viz::SingleReleaseCallback> previous_release_callback_;
};
- void SetMirrorClient(MirrorClient*);
+ void SetMirrorClient(scoped_refptr<MirrorClient> mirror_client);
void UseSharedBuffer(const gpu::MailboxHolder&);
void DoneWithSharedBuffer();
@@ -99,10 +108,9 @@ class PLATFORM_EXPORT XRWebGLDrawingBuffer
bool discard_framebuffer_supported,
bool want_alpha_channel,
bool want_depth_buffer,
- bool want_stencil_buffer,
- bool multiview_supported);
+ bool want_stencil_buffer);
- bool Initialize(const IntSize&, bool use_multisampling, bool use_multiview);
+ bool Initialize(const IntSize&, bool use_multisampling);
IntSize AdjustSize(const IntSize&);
@@ -151,7 +159,6 @@ class PLATFORM_EXPORT XRWebGLDrawingBuffer
bool depth_;
bool stencil_;
bool alpha_;
- bool multiview_;
enum AntialiasingMode {
kNone,
@@ -166,7 +173,7 @@ class PLATFORM_EXPORT XRWebGLDrawingBuffer
int max_texture_size_ = 0;
int sample_count_ = 0;
- MirrorClient* mirror_client_ = nullptr;
+ scoped_refptr<MirrorClient> mirror_client_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc b/chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc
index 0f9141b2e29..4cc66dadfbf 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc
@@ -28,6 +28,7 @@
#include <memory>
+#include "base/optional.h"
#include "build/build_config.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/blink/renderer/platform/fonts/text_run_paint_info.h"
@@ -58,6 +59,34 @@
namespace blink {
+class GraphicsContext::HighContrastFlags final {
+ STACK_ALLOCATED();
+
+ public:
+ // This helper's lifetime should never exceed |flags|'.
+ HighContrastFlags(const GraphicsContext* gc, const PaintFlags& flags) {
+ if (!gc->high_contrast_filter_) {
+ flags_ = &flags;
+ } else {
+ high_contrast_flags_ = flags;
+ if (flags.HasShader()) {
+ high_contrast_flags_->setColorFilter(gc->high_contrast_filter_);
+ } else {
+ high_contrast_flags_->setColor(
+ gc->high_contrast_filter_->filterColor(flags.getColor()));
+ }
+
+ flags_ = &high_contrast_flags_.value();
+ }
+ }
+
+ operator const PaintFlags&() const { return *flags_; }
+
+ private:
+ const PaintFlags* flags_;
+ base::Optional<PaintFlags> high_contrast_flags_;
+};
+
GraphicsContext::GraphicsContext(PaintController& paint_controller,
DisabledMode disable_context_or_painting,
SkMetaData* meta_data)
@@ -637,7 +666,7 @@ void GraphicsContext::DrawLine(const IntPoint& point1, const IntPoint& point2) {
// probably worth the speed up of no square root, which also won't be exact.
FloatSize disp = p2 - p1;
int length = SkScalarRoundToInt(disp.Width() + disp.Height());
- PaintFlags flags(ImmutableState()->StrokeFlags(length));
+ const HighContrastFlags flags(this, ImmutableState()->StrokeFlags(length));
if (pen_style == kDottedStroke) {
if (StrokeData::StrokeIsDashed(width, pen_style)) {
@@ -664,8 +693,7 @@ void GraphicsContext::DrawLine(const IntPoint& point1, const IntPoint& point2) {
}
AdjustLineToPixelBoundaries(p1, p2, width);
- canvas_->drawLine(p1.X(), p1.Y(), p2.X(), p2.Y(),
- ApplyHighContrastFilter(&flags));
+ canvas_->drawLine(p1.X(), p1.Y(), p2.X(), p2.Y(), flags);
}
void GraphicsContext::DrawLineForText(const FloatPoint& pt, float width) {
@@ -743,7 +771,7 @@ void GraphicsContext::DrawTextInternal(const Font& font,
return;
font.DrawText(canvas_, text_info, point, device_scale_factor_,
- ApplyHighContrastFilter(&flags));
+ HighContrastFlags(this, flags));
}
void GraphicsContext::DrawText(const Font& font,
@@ -788,7 +816,7 @@ void GraphicsContext::DrawTextInternal(const Font& font,
DrawTextPasses([&font, &text_info, &point, this](const PaintFlags& flags) {
font.DrawText(canvas_, text_info, point, device_scale_factor_,
- ApplyHighContrastFilter(&flags));
+ HighContrastFlags(this, flags));
});
}
@@ -816,7 +844,7 @@ void GraphicsContext::DrawEmphasisMarksInternal(const Font& font,
[&font, &text_info, &mark, &point, this](const PaintFlags& flags) {
font.DrawEmphasisMarks(canvas_, text_info, mark, point,
device_scale_factor_,
- ApplyHighContrastFilter(&flags));
+ HighContrastFlags(this, flags));
});
}
@@ -847,7 +875,7 @@ void GraphicsContext::DrawBidiText(
this](const PaintFlags& flags) {
if (font.DrawBidiText(canvas_, run_info, point,
custom_font_not_ready_action, device_scale_factor_,
- ApplyHighContrastFilter(&flags)))
+ HighContrastFlags(this, flags)))
paint_controller_.SetTextPainted();
});
}
@@ -882,7 +910,6 @@ void GraphicsContext::DrawImage(
image_flags.setBlendMode(op);
image_flags.setColor(SK_ColorBLACK);
image_flags.setFilterQuality(ComputeFilterQuality(image, dest, src));
- image_flags.setAntiAlias(ShouldAntialias());
if (ShouldApplyHighContrastFilterToImage(*image))
image_flags.setColorFilter(high_contrast_filter_);
image->Draw(canvas_, image_flags, dest, src, should_respect_image_orientation,
@@ -918,7 +945,6 @@ void GraphicsContext::DrawImageRRect(
image_flags.setColor(SK_ColorBLACK);
image_flags.setFilterQuality(
ComputeFilterQuality(image, dest.Rect(), src_rect));
- image_flags.setAntiAlias(ShouldAntialias());
bool use_shader = (visible_src == src_rect) &&
(respect_orientation == kDoNotRespectImageOrientation);
@@ -1011,7 +1037,7 @@ void GraphicsContext::DrawOval(const SkRect& oval, const PaintFlags& flags) {
return;
DCHECK(canvas_);
- canvas_->drawOval(oval, ApplyHighContrastFilter(&flags));
+ canvas_->drawOval(oval, HighContrastFlags(this, flags));
}
void GraphicsContext::DrawPath(const SkPath& path, const PaintFlags& flags) {
@@ -1019,7 +1045,7 @@ void GraphicsContext::DrawPath(const SkPath& path, const PaintFlags& flags) {
return;
DCHECK(canvas_);
- canvas_->drawPath(path, ApplyHighContrastFilter(&flags));
+ canvas_->drawPath(path, HighContrastFlags(this, flags));
}
void GraphicsContext::DrawRect(const SkRect& rect, const PaintFlags& flags) {
@@ -1027,7 +1053,7 @@ void GraphicsContext::DrawRect(const SkRect& rect, const PaintFlags& flags) {
return;
DCHECK(canvas_);
- canvas_->drawRect(rect, ApplyHighContrastFilter(&flags));
+ canvas_->drawRect(rect, HighContrastFlags(this, flags));
}
void GraphicsContext::DrawRRect(const SkRRect& rrect, const PaintFlags& flags) {
@@ -1035,7 +1061,7 @@ void GraphicsContext::DrawRRect(const SkRRect& rrect, const PaintFlags& flags) {
return;
DCHECK(canvas_);
- canvas_->drawRRect(rrect, ApplyHighContrastFilter(&flags));
+ canvas_->drawRRect(rrect, HighContrastFlags(this, flags));
}
void GraphicsContext::FillPath(const Path& path_to_fill) {
@@ -1423,28 +1449,7 @@ bool GraphicsContext::ShouldApplyHighContrastFilterToImage(Image& image) {
Color GraphicsContext::ApplyHighContrastFilter(const Color& input) const {
if (!high_contrast_filter_)
return input;
-
- SkColor sk_input =
- SkColorSetARGB(input.Alpha(), input.Red(), input.Green(), input.Blue());
- SkColor sk_output = high_contrast_filter_->filterColor(sk_input);
- return Color(MakeRGBA(SkColorGetR(sk_output), SkColorGetG(sk_output),
- SkColorGetB(sk_output), SkColorGetA(sk_output)));
-}
-
-PaintFlags GraphicsContext::ApplyHighContrastFilter(
- const PaintFlags* input) const {
- if (input && !high_contrast_filter_)
- return *input;
-
- PaintFlags output;
- if (input)
- output = *input;
- if (output.HasShader()) {
- output.setColorFilter(high_contrast_filter_);
- } else {
- output.setColor(high_contrast_filter_->filterColor(output.getColor()));
- }
- return output;
+ return Color(high_contrast_filter_->filterColor(input.Rgb()));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_context.h b/chromium/third_party/blink/renderer/platform/graphics/graphics_context.h
index bcde7276eff..f46176a479d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_context.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_context.h
@@ -88,7 +88,7 @@ class PLATFORM_EXPORT GraphicsContext {
bool ContextDisabled() const { return disabled_state_; }
- const HighContrastSettings& high_contrast_settings() {
+ const HighContrastSettings& high_contrast_settings() const {
return high_contrast_settings_;
}
@@ -466,9 +466,9 @@ class PLATFORM_EXPORT GraphicsContext {
const SkMetaData& MetaData() const { return meta_data_; }
+ class HighContrastFlags;
bool ShouldApplyHighContrastFilterToImage(Image&);
Color ApplyHighContrastFilter(const Color& input) const;
- PaintFlags ApplyHighContrastFilter(const PaintFlags* input) const;
// null indicates painting is contextDisabled. Never delete this object.
cc::PaintCanvas* canvas_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc
index 5a8572622a4..589c9d31b1d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc
@@ -80,6 +80,7 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient& client)
: client_(client),
prevent_contents_opaque_changes_(false),
draws_content_(false),
+ paints_hit_test_(false),
contents_visible_(true),
hit_testable_without_draws_content_(false),
needs_check_raster_invalidation_(false),
@@ -90,12 +91,12 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient& client)
parent_(nullptr),
mask_layer_(nullptr),
contents_clipping_mask_layer_(nullptr),
- paint_count_(0),
contents_layer_(nullptr),
contents_layer_id_(0),
rendering_context3d_(0),
weak_ptr_factory_(this) {
#if DCHECK_IS_ON()
+ DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
client.VerifyNotPainting();
#endif
layer_ = cc::PictureLayer::Create(this);
@@ -106,6 +107,7 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient& client)
}
GraphicsLayer::~GraphicsLayer() {
+ CcLayer()->ClearClient();
CcLayer()->SetLayerClient(nullptr);
SetContentsLayer(nullptr);
for (size_t i = 0; i < link_highlights_.size(); ++i)
@@ -150,6 +152,18 @@ void GraphicsLayer::SetIsContainerForFixedPositionLayers(bool is_container) {
CcLayer()->SetIsContainerForFixedPositionLayers(is_container);
}
+void GraphicsLayer::SetCompositingReasons(CompositingReasons reasons) {
+ CcLayer()->set_compositing_reasons(reasons);
+}
+
+CompositingReasons GraphicsLayer::GetCompositingReasons() const {
+ return CcLayer()->compositing_reasons();
+}
+
+void GraphicsLayer::SetOwnerNodeId(int node_id) {
+ CcLayer()->set_owner_node_id(node_id);
+}
+
void GraphicsLayer::SetParent(GraphicsLayer* layer) {
#if DCHECK_IS_ON()
DCHECK(!layer || !layer->HasAncestor(this));
@@ -244,8 +258,10 @@ void GraphicsLayer::RemoveFromParent() {
// When using layer lists, cc::Layers are created and removed in
// PaintArtifactCompositor.
if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() &&
- !RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ !RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
CcLayer()->RemoveFromParent();
+ } else {
+ SetPaintArtifactCompositorNeedsUpdate();
}
}
@@ -287,8 +303,8 @@ void GraphicsLayer::PaintRecursively() {
void GraphicsLayer::PaintRecursivelyInternal(
Vector<GraphicsLayer*>& repainted_layers) {
- if (DrawsContent()) {
- if (Paint(nullptr))
+ if (PaintsContentOrHitTest()) {
+ if (Paint())
repainted_layers.push_back(this);
}
@@ -301,8 +317,7 @@ void GraphicsLayer::PaintRecursivelyInternal(
child->PaintRecursivelyInternal(repainted_layers);
}
-bool GraphicsLayer::Paint(const IntRect* interest_rect,
- GraphicsContext::DisabledMode disabled_mode) {
+bool GraphicsLayer::Paint(GraphicsContext::DisabledMode disabled_mode) {
#if !DCHECK_IS_ON()
// TODO(crbug.com/853096): Investigate why we can ever reach here without
// a valid layer state. Seems to only happen on Android builds.
@@ -310,7 +325,7 @@ bool GraphicsLayer::Paint(const IntRect* interest_rect,
return false;
#endif
- if (PaintWithoutCommit(interest_rect, disabled_mode))
+ if (PaintWithoutCommit(disabled_mode))
GetPaintController().CommitNewDisplayItems();
else if (!needs_check_raster_invalidation_)
return false;
@@ -330,7 +345,7 @@ bool GraphicsLayer::Paint(const IntRect* interest_rect,
layer_state_->state, VisualRectSubpixelOffset(), this);
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() &&
- DrawsContent()) {
+ PaintsContentOrHitTest()) {
auto& tracking = EnsureRasterInvalidator().EnsureTracking();
tracking.CheckUnderInvalidations(DebugName(), CapturePaintRecord(),
InterestRect());
@@ -347,16 +362,20 @@ bool GraphicsLayer::Paint(const IntRect* interest_rect,
return true;
}
+bool GraphicsLayer::PaintWithoutCommitForTesting(
+ const base::Optional<IntRect>& interest_rect) {
+ return PaintWithoutCommit(GraphicsContext::kNothingDisabled,
+ base::OptionalOrNullptr(interest_rect));
+}
+
bool GraphicsLayer::PaintWithoutCommit(
- const IntRect* interest_rect,
- GraphicsContext::DisabledMode disabled_mode) {
- DCHECK(DrawsContent());
+ GraphicsContext::DisabledMode disabled_mode,
+ const IntRect* interest_rect) {
+ DCHECK(PaintsContentOrHitTest());
if (client_.ShouldThrottleRendering())
return false;
- IncrementPaintCount();
-
IntRect new_interest_rect;
if (!interest_rect) {
new_interest_rect =
@@ -384,7 +403,8 @@ bool GraphicsLayer::PaintWithoutCommit(
void GraphicsLayer::UpdateChildList() {
// When using layer lists, cc::Layers are created in PaintArtifactCompositor.
if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() ||
- RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ SetPaintArtifactCompositorNeedsUpdate();
return;
}
@@ -431,6 +451,12 @@ void GraphicsLayer::UpdateContentsRect() {
if (!contents_layer)
return;
+ if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
+ const auto& offset = GetContentsOffsetFromTransformNode();
+ contents_layer->SetOffsetToTransformParent(
+ gfx::Vector2dF(offset.X(), offset.Y()));
+ SetPaintArtifactCompositorNeedsUpdate();
+ }
contents_layer->SetPosition(
FloatPoint(contents_rect_.X(), contents_rect_.Y()));
if (!image_layer_) {
@@ -525,16 +551,13 @@ void GraphicsLayer::SetupContentsLayer(cc::Layer* contents_layer) {
// Insert the content layer first. Video elements require this, because they
// have shadow content that must display in front of the video.
if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() &&
- !RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ !RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
CcLayer()->InsertChild(contents_layer_, 0);
}
cc::PictureLayer* border_cc_layer =
contents_clipping_mask_layer_ ? contents_clipping_mask_layer_->CcLayer()
: nullptr;
contents_layer_->SetMaskLayer(border_cc_layer);
- if (border_cc_layer)
- border_cc_layer->set_is_rounded_corner_mask(true);
-
contents_layer_->Set3dSortingContextId(rendering_context3d_);
}
@@ -722,6 +745,10 @@ void GraphicsLayer::SetContentsVisible(bool contents_visible) {
UpdateLayerIsDrawable();
}
+void GraphicsLayer::SetPaintArtifactCompositorNeedsUpdate() const {
+ client_.SetPaintArtifactCompositorNeedsUpdate();
+}
+
void GraphicsLayer::SetClipParent(cc::Layer* parent) {
has_clip_parent_ = !!parent;
CcLayer()->SetClipParent(parent);
@@ -751,15 +778,12 @@ void GraphicsLayer::SetContentsOpaque(bool opaque) {
contents_layer_->SetContentsOpaque(opaque);
}
-void GraphicsLayer::SetMaskLayer(GraphicsLayer* mask_layer,
- bool is_rounded_corner_mask) {
+void GraphicsLayer::SetMaskLayer(GraphicsLayer* mask_layer) {
if (mask_layer == mask_layer_)
return;
mask_layer_ = mask_layer;
CcLayer()->SetMaskLayer(mask_layer_ ? mask_layer_->CcLayer() : nullptr);
- if (mask_layer_)
- mask_layer_->CcLayer()->set_is_rounded_corner_mask(is_rounded_corner_mask);
}
void GraphicsLayer::SetContentsClippingMaskLayer(
@@ -775,9 +799,6 @@ void GraphicsLayer::SetContentsClippingMaskLayer(
contents_clipping_mask_layer_ ? contents_clipping_mask_layer_->CcLayer()
: nullptr;
contents_layer->SetMaskLayer(contents_clipping_mask_cc_layer);
- // Contents clipping mask layesrs (aka child clipping mask layer) is always
- // a rounded corner mask.
- contents_layer->set_is_rounded_corner_mask(true);
UpdateContentsRect();
}
@@ -829,7 +850,7 @@ void GraphicsLayer::SetContentsNeedsDisplay() {
}
void GraphicsLayer::SetNeedsDisplay() {
- if (!DrawsContent())
+ if (!PaintsContentOrHitTest())
return;
CcLayer()->SetNeedsDisplay();
@@ -846,7 +867,7 @@ void GraphicsLayer::SetNeedsDisplay() {
}
void GraphicsLayer::SetNeedsDisplayInRect(const IntRect& rect) {
- DCHECK(DrawsContent());
+ DCHECK(PaintsContentOrHitTest());
CcLayer()->SetNeedsDisplayRect(rect);
for (auto* link_highlight : link_highlights_)
@@ -920,8 +941,11 @@ void GraphicsLayer::SetFilters(CompositorFilterOperations filters) {
CcLayer()->SetFilters(filters.ReleaseCcFilterOperations());
}
-void GraphicsLayer::SetBackdropFilters(CompositorFilterOperations filters) {
+void GraphicsLayer::SetBackdropFilters(
+ CompositorFilterOperations filters,
+ const gfx::RectF& backdrop_filter_bounds) {
CcLayer()->SetBackdropFilters(filters.ReleaseCcFilterOperations());
+ CcLayer()->SetBackdropFilterBounds(backdrop_filter_bounds);
}
void GraphicsLayer::SetStickyPositionConstraint(
@@ -962,7 +986,7 @@ std::unique_ptr<base::trace_event::TracedValue> GraphicsLayer::TakeDebugInfo(
traced_value->BeginArray("compositing_reasons");
for (const char* description :
- CompositingReason::Descriptions(compositing_reasons_))
+ CompositingReason::Descriptions(GetCompositingReasons()))
traced_value->AppendString(description);
traced_value->EndArray();
@@ -972,8 +996,8 @@ std::unique_ptr<base::trace_event::TracedValue> GraphicsLayer::TakeDebugInfo(
traced_value->AppendString(description);
traced_value->EndArray();
- if (owner_node_id_)
- traced_value->SetInteger("owner_node", owner_node_id_);
+ if (auto node_id = layer_->owner_node_id())
+ traced_value->SetInteger("owner_node", node_id);
if (auto* tracking = GetRasterInvalidationTracking()) {
tracking->AddToTracedValue(*traced_value);
@@ -988,7 +1012,7 @@ void GraphicsLayer::DidChangeScrollbarsHiddenIfOverlay(bool hidden) {
}
PaintController& GraphicsLayer::GetPaintController() const {
- CHECK(DrawsContent());
+ CHECK(PaintsContentOrHitTest());
if (!paint_controller_)
paint_controller_ = PaintController::Create();
return *paint_controller_;
@@ -1006,7 +1030,7 @@ CompositorElementId GraphicsLayer::GetElementId() const {
}
sk_sp<PaintRecord> GraphicsLayer::CapturePaintRecord() const {
- DCHECK(DrawsContent());
+ DCHECK(PaintsContentOrHitTest());
if (client_.ShouldThrottleRendering())
return sk_sp<PaintRecord>(new PaintRecord);
@@ -1025,6 +1049,9 @@ void GraphicsLayer::SetLayerState(const PropertyTreeState& layer_state,
DCHECK(layer_state.Transform() && layer_state.Clip() && layer_state.Effect());
if (layer_state_) {
+ if (layer_state_->state == layer_state &&
+ layer_state_->offset == layer_offset)
+ return;
layer_state_->state = layer_state;
layer_state_->offset = layer_offset;
} else {
@@ -1036,29 +1063,25 @@ void GraphicsLayer::SetLayerState(const PropertyTreeState& layer_state,
CcLayer()->SetOffsetToTransformParent(
gfx::Vector2dF(layer_offset.X(), layer_offset.Y()));
- if (!contents_layer_state_ && ContentsLayer()) {
+ if (ContentsLayer()) {
+ const auto& offset = GetContentsOffsetFromTransformNode();
ContentsLayer()->SetOffsetToTransformParent(
- gfx::Vector2dF(layer_offset.X(), layer_offset.Y()));
+ gfx::Vector2dF(offset.X(), offset.Y()));
}
+ SetPaintArtifactCompositorNeedsUpdate();
}
}
-void GraphicsLayer::SetContentsLayerState(const PropertyTreeState& layer_state,
- const IntPoint& layer_offset) {
+void GraphicsLayer::SetContentsPropertyTreeState(
+ const PropertyTreeState& layer_state) {
DCHECK(layer_state.Transform() && layer_state.Clip() && layer_state.Effect());
DCHECK(ContentsLayer());
- if (contents_layer_state_) {
- contents_layer_state_->state = layer_state;
- contents_layer_state_->offset = layer_offset;
+ if (contents_property_tree_state_) {
+ *contents_property_tree_state_ = layer_state;
} else {
- contents_layer_state_ =
- std::make_unique<LayerState>(LayerState{layer_state, layer_offset});
- }
-
- if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
- ContentsLayer()->SetOffsetToTransformParent(
- gfx::Vector2dF(layer_offset.X(), layer_offset.Y()));
+ contents_property_tree_state_ =
+ std::make_unique<PropertyTreeState>(layer_state);
}
}
@@ -1094,7 +1117,7 @@ scoped_refptr<cc::DisplayItemList> GraphicsLayer::PaintContentsToDisplayList(
// occurs in LocalFrameView::PaintTree() which calls GraphicsLayer::Paint();
// this method merely copies the painted output to the cc::DisplayItemList.
if (painting_control != PAINTING_BEHAVIOR_NORMAL)
- Paint(nullptr, disabled_mode);
+ Paint(disabled_mode);
auto display_list = base::MakeRefCounted<cc::DisplayItemList>();
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h
index 954f933c69e..71f07812a9c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h
@@ -89,19 +89,17 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
GraphicsLayerClient& Client() const { return client_; }
- void SetCompositingReasons(CompositingReasons reasons) {
- compositing_reasons_ = reasons;
- }
- CompositingReasons GetCompositingReasons() const {
- return compositing_reasons_;
- }
+ void SetCompositingReasons(CompositingReasons reasons);
+ CompositingReasons GetCompositingReasons() const;
+
SquashingDisallowedReasons GetSquashingDisallowedReasons() const {
return squashing_disallowed_reasons_;
}
void SetSquashingDisallowedReasons(SquashingDisallowedReasons reasons) {
squashing_disallowed_reasons_ = reasons;
}
- void SetOwnerNodeId(int id) { owner_node_id_ = id; }
+
+ void SetOwnerNodeId(int id);
GraphicsLayer* Parent() const { return parent_; }
void SetParent(GraphicsLayer*); // Internal use only.
@@ -119,7 +117,7 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
void RemoveFromParent();
GraphicsLayer* MaskLayer() const { return mask_layer_; }
- void SetMaskLayer(GraphicsLayer*, bool is_rounded_corner_mask);
+ void SetMaskLayer(GraphicsLayer*);
GraphicsLayer* ContentsClippingMaskLayer() const {
return contents_clipping_mask_layer_;
@@ -159,12 +157,24 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
bool DrawsContent() const { return draws_content_; }
void SetDrawsContent(bool);
+ // False if no hit test display items will be painted onto this GraphicsLayer.
+ // This is different from |DrawsContent| because hit test display items are
+ // internal to blink and are not copied to the cc::Layer's display list.
+ bool PaintsHitTest() const { return paints_hit_test_; }
+ void SetPaintsHitTest(bool paints) { paints_hit_test_ = paints; };
+
+ bool PaintsContentOrHitTest() const {
+ return draws_content_ || paints_hit_test_;
+ }
+
bool ContentsAreVisible() const { return contents_visible_; }
void SetContentsVisible(bool);
void SetScrollParent(cc::Layer*);
void SetClipParent(cc::Layer*);
+ void SetPaintArtifactCompositorNeedsUpdate() const;
+
// For special cases, e.g. drawing missing tiles on Android.
// The compositor should never paint this color in normal cases because the
// Layer will paint the background by itself.
@@ -192,7 +202,7 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
}
void SetFilters(CompositorFilterOperations);
- void SetBackdropFilters(CompositorFilterOperations);
+ void SetBackdropFilters(CompositorFilterOperations, const gfx::RectF&);
void SetStickyPositionConstraint(const cc::LayerStickyPositionConstraint&);
@@ -227,8 +237,6 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
// For hosting this GraphicsLayer in a native layer hierarchy.
cc::PictureLayer* CcLayer() const;
- int PaintCount() const { return paint_count_; }
-
// Return a string with a human readable form of the layer tree. If debug is
// true, pointers for the layers and timing data will be included in the
// returned string.
@@ -256,8 +264,7 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
IntRect InterestRect();
void PaintRecursively();
// Returns true if this layer is repainted.
- bool Paint(const IntRect* interest_rect,
- GraphicsContext::DisabledMode = GraphicsContext::kNothingDisabled);
+ bool Paint(GraphicsContext::DisabledMode = GraphicsContext::kNothingDisabled);
// cc::LayerClient implementation.
std::unique_ptr<base::trace_event::TracedValue> TakeDebugInfo(
@@ -289,15 +296,16 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
}
IntPoint GetOffsetFromTransformNode() const { return layer_state_->offset; }
- void SetContentsLayerState(const PropertyTreeState&,
- const IntPoint& layer_offset);
+ void SetContentsPropertyTreeState(const PropertyTreeState&);
const PropertyTreeState& GetContentsPropertyTreeState() const {
- return contents_layer_state_ ? contents_layer_state_->state
- : GetPropertyTreeState();
+ return contents_property_tree_state_ ? *contents_property_tree_state_
+ : GetPropertyTreeState();
}
IntPoint GetContentsOffsetFromTransformNode() const {
- return contents_layer_state_ ? contents_layer_state_->offset
- : GetOffsetFromTransformNode();
+ auto offset = contents_rect_.Location();
+ if (layer_state_)
+ offset = offset + GetOffsetFromTransformNode();
+ return offset;
}
// Capture the last painted result into a PaintRecord. This GraphicsLayer
@@ -311,16 +319,18 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
bool HasScrollParent() const { return has_scroll_parent_; }
bool HasClipParent() const { return has_clip_parent_; }
+ bool PaintWithoutCommitForTesting(
+ const base::Optional<IntRect>& interest_rect = base::nullopt);
+
protected:
String DebugName(cc::Layer*) const;
explicit GraphicsLayer(GraphicsLayerClient&);
+ private:
friend class CompositedLayerMappingTest;
- friend class PaintControllerPaintTestBase;
friend class GraphicsLayerTest;
- private:
// cc::ContentLayerClient implementation.
gfx::Rect PaintableRegion() final { return InterestRect(); }
scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList(
@@ -330,10 +340,10 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
void PaintRecursivelyInternal(Vector<GraphicsLayer*>& repainted_layers);
- // Returns true if PaintController::paintArtifact() changed and needs commit.
+ // Returns true if PaintController::PaintArtifact() changed and needs commit.
bool PaintWithoutCommit(
- const IntRect* interest_rect,
- GraphicsContext::DisabledMode = GraphicsContext::kNothingDisabled);
+ GraphicsContext::DisabledMode = GraphicsContext::kNothingDisabled,
+ const IntRect* interest_rect = nullptr);
// Adds a child without calling updateChildList(), so that adding children
// can be batched before updating.
@@ -343,8 +353,6 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
bool HasAncestor(GraphicsLayer*) const;
#endif
- void IncrementPaintCount() { ++paint_count_; }
-
// Helper functions used by settors to keep layer's the state consistent.
void UpdateChildList();
void UpdateLayerIsDrawable();
@@ -370,6 +378,7 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
bool prevent_contents_opaque_changes_ : 1;
bool draws_content_ : 1;
+ bool paints_hit_test_ : 1;
bool contents_visible_ : 1;
bool hit_testable_without_draws_content_ : 1;
bool needs_check_raster_invalidation_ : 1;
@@ -391,8 +400,6 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
IntRect contents_rect_;
- int paint_count_;
-
scoped_refptr<cc::PictureLayer> layer_;
scoped_refptr<cc::PictureImageLayer> image_layer_;
IntSize image_size_;
@@ -408,10 +415,8 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
int rendering_context3d_;
- CompositingReasons compositing_reasons_ = CompositingReason::kNone;
SquashingDisallowedReasons squashing_disallowed_reasons_ =
SquashingDisallowedReason::kNone;
- int owner_node_id_ = 0;
mutable std::unique_ptr<PaintController> paint_controller_;
@@ -422,7 +427,7 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
IntPoint offset;
};
std::unique_ptr<LayerState> layer_state_;
- std::unique_ptr<LayerState> contents_layer_state_;
+ std::unique_ptr<PropertyTreeState> contents_property_tree_state_;
std::unique_ptr<RasterInvalidator> raster_invalidator_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_client.h b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_client.h
index 7561489f69c..f55c529d768 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_client.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_client.h
@@ -97,6 +97,8 @@ class PLATFORM_EXPORT GraphicsLayerClient {
virtual void SetOverlayScrollbarsHidden(bool) {}
+ virtual void SetPaintArtifactCompositorNeedsUpdate() const {}
+
virtual String DebugName(const GraphicsLayer*) const = 0;
virtual const ScrollableArea* GetScrollableAreaForTesting(
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc
index e79095e8fbf..ac3a7883312 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc
@@ -49,10 +49,6 @@ class GraphicsLayerTest : public testing::Test, public PaintTestConfigurations {
~GraphicsLayerTest() = default;
protected:
- bool PaintWithoutCommit(GraphicsLayer& layer, const IntRect* interest_rect) {
- return layer.PaintWithoutCommit(interest_rect);
- }
-
void CommitAndFinishCycle(GraphicsLayer& layer) {
layer.GetPaintController().CommitNewDisplayItems();
layer.GetPaintController().FinishCycle();
@@ -82,25 +78,26 @@ INSTANTIATE_TEST_CASE_P(All,
TEST_P(GraphicsLayerTest, Paint) {
IntRect interest_rect(1, 2, 3, 4);
- EXPECT_TRUE(PaintWithoutCommit(layers_.graphics_layer(), &interest_rect));
- CommitAndFinishCycle(layers_.graphics_layer());
+ auto& layer = layers_.graphics_layer();
+ EXPECT_TRUE(layer.PaintWithoutCommitForTesting(interest_rect));
+ CommitAndFinishCycle(layer);
layers_.graphics_layer_client().SetNeedsRepaint(true);
- EXPECT_TRUE(PaintWithoutCommit(layers_.graphics_layer(), &interest_rect));
- CommitAndFinishCycle(layers_.graphics_layer());
+ EXPECT_TRUE(layer.PaintWithoutCommitForTesting(interest_rect));
+ CommitAndFinishCycle(layer);
layers_.graphics_layer_client().SetNeedsRepaint(false);
- EXPECT_FALSE(PaintWithoutCommit(layers_.graphics_layer(), &interest_rect));
+ EXPECT_FALSE(layer.PaintWithoutCommitForTesting(interest_rect));
interest_rect.Move(IntSize(10, 20));
- EXPECT_TRUE(PaintWithoutCommit(layers_.graphics_layer(), &interest_rect));
- CommitAndFinishCycle(layers_.graphics_layer());
- EXPECT_FALSE(PaintWithoutCommit(layers_.graphics_layer(), &interest_rect));
+ EXPECT_TRUE(layer.PaintWithoutCommitForTesting(interest_rect));
+ CommitAndFinishCycle(layer);
+ EXPECT_FALSE(layer.PaintWithoutCommitForTesting(interest_rect));
layers_.graphics_layer().SetNeedsDisplay();
- EXPECT_TRUE(PaintWithoutCommit(layers_.graphics_layer(), &interest_rect));
- CommitAndFinishCycle(layers_.graphics_layer());
- EXPECT_FALSE(PaintWithoutCommit(layers_.graphics_layer(), &interest_rect));
+ EXPECT_TRUE(layer.PaintWithoutCommitForTesting(interest_rect));
+ CommitAndFinishCycle(layer);
+ EXPECT_FALSE(layer.PaintWithoutCommitForTesting(interest_rect));
}
TEST_P(GraphicsLayerTest, PaintRecursively) {
@@ -158,4 +155,21 @@ TEST_P(GraphicsLayerTest, SetDrawsContentFalse) {
EXPECT_EQ(nullptr, GetInternalRasterInvalidator(layers_.graphics_layer()));
}
+TEST_P(GraphicsLayerTest, CcLayerClient) {
+ auto graphics_layer =
+ std::make_unique<FakeGraphicsLayer>(layers_.graphics_layer_client());
+ graphics_layer->SetDrawsContent(true);
+ scoped_refptr<cc::PictureLayer> cc_layer = graphics_layer->CcLayer();
+ ASSERT_TRUE(cc_layer);
+ EXPECT_TRUE(cc_layer->DrawsContent());
+ EXPECT_TRUE(cc_layer->client());
+ EXPECT_TRUE(cc_layer->GetLayerClientForTesting());
+
+ graphics_layer.reset();
+ EXPECT_FALSE(cc_layer->DrawsContent());
+ EXPECT_FALSE(cc_layer->client());
+ EXPECT_FALSE(cc_layer->GetLayerClientForTesting());
+ EXPECT_FALSE(cc_layer->GetPicture());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image.cc b/chromium/third_party/blink/renderer/platform/graphics/image.cc
index 4b07a4b2fdc..efa5fa09313 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/image.cc
@@ -303,7 +303,8 @@ namespace {
sk_sp<PaintShader> CreatePatternShader(const PaintImage& image,
const SkMatrix& shader_matrix,
- const PaintFlags& paint,
+ SkFilterQuality quality_to_use,
+ bool should_antialias,
const FloatSize& spacing,
SkShader::TileMode tmx,
SkShader::TileMode tmy) {
@@ -318,7 +319,10 @@ sk_sp<PaintShader> CreatePatternShader(const PaintImage& image,
PaintRecorder recorder;
cc::PaintCanvas* canvas = recorder.beginRecording(tile_rect);
- canvas->drawImage(image, 0, 0, &paint);
+ PaintFlags flags;
+ flags.setAntiAlias(should_antialias);
+ flags.setFilterQuality(quality_to_use);
+ canvas->drawImage(image, 0, 0, &flags);
return PaintShader::MakePaintRecord(recorder.finishRecordingAsPicture(),
tile_rect, tmx, tmy, &shader_matrix);
@@ -389,22 +393,22 @@ void Image::DrawPattern(GraphicsContext& context,
const auto tmy = ComputeTileMode(dest_rect.Y(), dest_rect.MaxY(), adjusted_y,
adjusted_y + tile_size.Height());
- PaintFlags flags = context.FillFlags();
- flags.setColor(SK_ColorBLACK);
- flags.setBlendMode(composite_op);
- flags.setFilterQuality(
- context.ComputeFilterQuality(this, dest_rect, FloatRect(subset_rect)));
- flags.setAntiAlias(context.ShouldAntialias());
- flags.setShader(CreatePatternShader(
- image, local_matrix, flags,
+ SkFilterQuality quality_to_use =
+ context.ComputeFilterQuality(this, dest_rect, FloatRect(subset_rect));
+ sk_sp<PaintShader> tile_shader = CreatePatternShader(
+ image, local_matrix, quality_to_use, context.ShouldAntialias(),
FloatSize(repeat_spacing.Width() / scale_src_to_dest.Width(),
repeat_spacing.Height() / scale_src_to_dest.Height()),
- tmx, tmy));
+ tmx, tmy);
+
+ PaintFlags flags = context.FillFlags();
// If the shader could not be instantiated (e.g. non-invertible matrix),
// draw transparent.
// Note: we can't simply bail, because of arbitrary blend mode.
- if (!flags.HasShader())
- flags.setColor(SK_ColorTRANSPARENT);
+ flags.setColor(tile_shader ? SK_ColorBLACK : SK_ColorTRANSPARENT);
+ flags.setBlendMode(composite_op);
+ flags.setFilterQuality(quality_to_use);
+ flags.setShader(std::move(tile_shader));
context.DrawRect(dest_rect, flags);
@@ -466,7 +470,7 @@ FloatRect Image::ComputeSubsetForBackground(const FloatRect& phase_and_size,
const FloatRect& subset,
const FloatSize& intrinsic_size) {
// TODO(schenney): Re-enable this after determining why it fails for
- // SPv2, and maybe other cases.
+ // CAP, and maybe other cases.
// DCHECK(phase_and_size.Contains(subset));
const FloatSize scale(phase_and_size.Width() / intrinsic_size.Width(),
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image_pattern.cc b/chromium/third_party/blink/renderer/platform/graphics/image_pattern.cc
index 62a2e0e25d6..7632a4e9239 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image_pattern.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/image_pattern.cc
@@ -5,11 +5,8 @@
#include "third_party/blink/renderer/platform/graphics/image_pattern.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_shader.h"
-#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/skia/include/core/SkImage.h"
-#include "third_party/skia/include/core/SkSurface.h"
namespace blink {
@@ -20,13 +17,6 @@ scoped_refptr<ImagePattern> ImagePattern::Create(scoped_refptr<Image> image,
ImagePattern::ImagePattern(scoped_refptr<Image> image, RepeatMode repeat_mode)
: Pattern(repeat_mode), tile_image_(image->PaintImageForCurrentFrame()) {
- previous_local_matrix_.setIdentity();
-}
-
-bool ImagePattern::IsLocalMatrixChanged(const SkMatrix& local_matrix) const {
- if (IsRepeatXY())
- return Pattern::IsLocalMatrixChanged(local_matrix);
- return local_matrix != previous_local_matrix_;
}
sk_sp<PaintShader> ImagePattern::CreateShader(const SkMatrix& local_matrix) {
@@ -34,45 +24,11 @@ sk_sp<PaintShader> ImagePattern::CreateShader(const SkMatrix& local_matrix) {
return PaintShader::MakeColor(SK_ColorTRANSPARENT);
}
- if (IsRepeatXY()) {
- // Fast path: for repeatXY we just return a shader from the original image.
- return PaintShader::MakeImage(tile_image_, SkShader::kRepeat_TileMode,
- SkShader::kRepeat_TileMode, &local_matrix);
- }
-
- // Skia does not have a "draw the tile only once" option. Clamp_TileMode
- // repeats the last line of the image after drawing one tile. To avoid
- // filling the space with arbitrary pixels, this workaround forces the
- // image to have a line of transparent pixels on the "repeated" edge(s),
- // thus causing extra space to be transparent filled.
- SkShader::TileMode tile_mode_x =
- IsRepeatX() ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
- SkShader::TileMode tile_mode_y =
- IsRepeatY() ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
- int border_pixel_x = IsRepeatX() ? 0 : 1;
- int border_pixel_y = IsRepeatY() ? 0 : 1;
-
- // Create a transparent image 2 pixels wider and/or taller than the
- // original, then copy the orignal into the middle of it.
- const SkRect tile_bounds =
- SkRect::MakeWH(tile_image_.width() + 2 * border_pixel_x,
- tile_image_.height() + 2 * border_pixel_y);
- PaintRecorder recorder;
- auto* canvas = recorder.beginRecording(tile_bounds);
-
- cc::PaintFlags paint;
- paint.setBlendMode(SkBlendMode::kSrc);
- canvas->drawImage(tile_image_, border_pixel_x, border_pixel_y, &paint);
-
- previous_local_matrix_ = local_matrix;
- SkMatrix adjusted_matrix(local_matrix);
- adjusted_matrix.postTranslate(-border_pixel_x, -border_pixel_y);
-
- // Note: we specify kFixedScale to lock-in the resolution (for 1px padding in
- // particular).
- return PaintShader::MakePaintRecord(
- recorder.finishRecordingAsPicture(), tile_bounds, tile_mode_x,
- tile_mode_y, &adjusted_matrix, PaintShader::ScalingBehavior::kFixedScale);
+ return PaintShader::MakeImage(
+ tile_image_,
+ IsRepeatX() ? SkShader::kRepeat_TileMode : SkShader::kDecal_TileMode,
+ IsRepeatY() ? SkShader::kRepeat_TileMode : SkShader::kDecal_TileMode,
+ &local_matrix);
}
bool ImagePattern::IsTextureBacked() const {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image_pattern.h b/chromium/third_party/blink/renderer/platform/graphics/image_pattern.h
index db42125f29e..cea1b6b337d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image_pattern.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/image_pattern.h
@@ -20,11 +20,9 @@ class PLATFORM_EXPORT ImagePattern final : public Pattern {
protected:
sk_sp<PaintShader> CreateShader(const SkMatrix&) override;
- bool IsLocalMatrixChanged(const SkMatrix&) const override;
private:
ImagePattern(scoped_refptr<Image>, RepeatMode);
- SkMatrix previous_local_matrix_;
PaintImage tile_image_;
};
diff --git a/chromium/third_party/blink/renderer/platform/graphics/intercepting_canvas.h b/chromium/third_party/blink/renderer/platform/graphics/intercepting_canvas.h
index f17b64acc09..78164e773fc 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/intercepting_canvas.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/intercepting_canvas.h
@@ -116,20 +116,6 @@ class InterceptingCanvasBase : public SkCanvas {
void onDrawDRRect(const SkRRect& outer,
const SkRRect& inner,
const SkPaint&) override = 0;
- void onDrawText(const void* text,
- size_t byte_length,
- SkScalar x,
- SkScalar y,
- const SkPaint&) override = 0;
- void onDrawPosText(const void* text,
- size_t byte_length,
- const SkPoint pos[],
- const SkPaint&) override = 0;
- void onDrawPosTextH(const void* text,
- size_t byte_length,
- const SkScalar xpos[],
- SkScalar const_y,
- const SkPaint&) override = 0;
void onDrawTextBlob(const SkTextBlob*,
SkScalar x,
SkScalar y,
@@ -258,32 +244,6 @@ class InterceptingCanvas : public InterceptingCanvasBase {
this->SkCanvas::onDrawDRRect(outer, inner, paint);
}
- void onDrawText(const void* text,
- size_t byte_length,
- SkScalar x,
- SkScalar y,
- const SkPaint& paint) override {
- Interceptor interceptor(this);
- this->SkCanvas::onDrawText(text, byte_length, x, y, paint);
- }
-
- void onDrawPosText(const void* text,
- size_t byte_length,
- const SkPoint pos[],
- const SkPaint& paint) override {
- Interceptor interceptor(this);
- this->SkCanvas::onDrawPosText(text, byte_length, pos, paint);
- }
-
- void onDrawPosTextH(const void* text,
- size_t byte_length,
- const SkScalar xpos[],
- SkScalar const_y,
- const SkPaint& paint) override {
- Interceptor interceptor(this);
- this->SkCanvas::onDrawPosTextH(text, byte_length, xpos, const_y, paint);
- }
-
void onDrawTextBlob(const SkTextBlob* blob,
SkScalar x,
SkScalar y,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/link_highlight.h b/chromium/third_party/blink/renderer/platform/graphics/link_highlight.h
index 4044ad955f3..4dfc5a27c60 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/link_highlight.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/link_highlight.h
@@ -24,9 +24,11 @@ class PLATFORM_EXPORT LinkHighlight : public DisplayItemClient {
virtual void ClearCurrentGraphicsLayer() = 0;
virtual cc::Layer* Layer() = 0;
- virtual const EffectPaintPropertyNode* effect() = 0;
+ virtual const EffectPaintPropertyNode* effect() const = 0;
// DisplayItemClient methods
+ // TODO(wangxianzhu): This class doesn't need to be a DisplayItemClient in
+ // CompositeAfterPaint.
String DebugName() const final { return "LinkHighlight"; }
LayoutRect VisualRect() const final { return LayoutRect(); }
};
diff --git a/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.cc b/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.cc
index 0b830191a69..849372c2853 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.cc
@@ -31,6 +31,8 @@
#include "third_party/blink/renderer/platform/graphics/logging_canvas.h"
#include <unicode/unistr.h>
+
+#include "base/stl_util.h"
#include "base/sys_byteorder.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
@@ -39,7 +41,6 @@
#include "third_party/blink/renderer/platform/image-encoders/image_encoder.h"
#include "third_party/blink/renderer/platform/wtf/hex_number.h"
#include "third_party/blink/renderer/platform/wtf/text/base64.h"
-#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkPaint.h"
@@ -234,7 +235,7 @@ std::unique_ptr<JSONObject> ObjectForSkPath(const SkPath& path) {
std::unique_ptr<JSONObject> path_point_item = JSONObject::Create();
path_point_item->SetString("verb", verb_params.name);
DCHECK_LE(verb_params.point_count + verb_params.point_offset,
- arraysize(points));
+ base::size(points));
path_point_item->SetArray(
"points", ArrayForSkPoints(verb_params.point_count,
points + verb_params.point_offset));
@@ -341,18 +342,11 @@ void AppendFlagToString(String* flags_string, bool is_set, const String& name) {
}
String StringForSkPaintFlags(const SkPaint& paint) {
- if (!paint.getFlags())
+ if (!paint.isAntiAlias() && !paint.isDither())
return "none";
String flags_string = "";
AppendFlagToString(&flags_string, paint.isAntiAlias(), "AntiAlias");
AppendFlagToString(&flags_string, paint.isDither(), "Dither");
- AppendFlagToString(&flags_string, paint.isFakeBoldText(), "FakeBoldText");
- AppendFlagToString(&flags_string, paint.isLinearText(), "LinearText");
- AppendFlagToString(&flags_string, paint.isSubpixelText(), "SubpixelText");
- AppendFlagToString(&flags_string, paint.isLCDRenderText(), "LCDRenderText");
- AppendFlagToString(&flags_string, paint.isEmbeddedBitmapText(),
- "EmbeddedBitmapText");
- AppendFlagToString(&flags_string, paint.isAutohinted(), "Autohinted");
return flags_string;
}
@@ -414,43 +408,8 @@ String StyleName(SkPaint::Style style) {
};
}
-String TextEncodingName(SkPaint::TextEncoding encoding) {
- switch (encoding) {
- case SkPaint::kUTF8_TextEncoding:
- return "UTF-8";
- case SkPaint::kUTF16_TextEncoding:
- return "UTF-16";
- case SkPaint::kUTF32_TextEncoding:
- return "UTF-32";
- case SkPaint::kGlyphID_TextEncoding:
- return "GlyphID";
- default:
- NOTREACHED();
- return "?";
- };
-}
-
-String HintingName(SkFontHinting hinting) {
- switch (hinting) {
- case SkFontHinting::kNone:
- return "None";
- case SkFontHinting::kSlight:
- return "Slight";
- case SkFontHinting::kNormal:
- return "Normal";
- case SkFontHinting::kFull:
- return "Full";
- default:
- NOTREACHED();
- return "?";
- };
-}
-
std::unique_ptr<JSONObject> ObjectForSkPaint(const SkPaint& paint) {
std::unique_ptr<JSONObject> paint_item = JSONObject::Create();
- paint_item->SetDouble("textSize", paint.getTextSize());
- paint_item->SetDouble("textScaleX", paint.getTextScaleX());
- paint_item->SetDouble("textSkewX", paint.getTextSkewX());
if (SkShader* shader = paint.getShader())
paint_item->SetObject("shader", ObjectForSkShader(*shader));
paint_item->SetString("color", StringForSkColor(paint.getColor()));
@@ -462,9 +421,6 @@ std::unique_ptr<JSONObject> ObjectForSkPaint(const SkPaint& paint) {
paint_item->SetString("strokeCap", StrokeCapName(paint.getStrokeCap()));
paint_item->SetString("strokeJoin", StrokeJoinName(paint.getStrokeJoin()));
paint_item->SetString("styleName", StyleName(paint.getStyle()));
- paint_item->SetString("textEncoding",
- TextEncodingName(paint.getTextEncoding()));
- paint_item->SetString("hinting", HintingName(paint.getHinting()));
if (paint.getBlendMode() != SkBlendMode::kSrcOver)
paint_item->SetString("blendMode", SkBlendMode_Name(paint.getBlendMode()));
if (paint.getImageFilter())
@@ -472,14 +428,6 @@ std::unique_ptr<JSONObject> ObjectForSkPaint(const SkPaint& paint) {
return paint_item;
}
-std::unique_ptr<JSONArray> ArrayForSkScalars(size_t n,
- const SkScalar scalars[]) {
- std::unique_ptr<JSONArray> scalars_array = JSONArray::Create();
- for (size_t i = 0; i < n; ++i)
- scalars_array->PushDouble(scalars[i]);
- return scalars_array;
-}
-
String ClipOpName(SkClipOp op) {
switch (op) {
case SkClipOp::kDifference:
@@ -491,58 +439,6 @@ String ClipOpName(SkClipOp op) {
};
}
-String SaveLayerFlagsToString(SkCanvas::SaveLayerFlags flags) {
- String flags_string = "";
- if (flags & SkCanvas::kPreserveLCDText_SaveLayerFlag)
- flags_string.append("kPreserveLCDText_SaveLayerFlag ");
- return flags_string;
-}
-
-String StringForUTF32LEText(const void* text, size_t byte_length) {
- icu::UnicodeString utf16;
-#if defined(ARCH_CPU_BIG_ENDIAN)
- // Swap LE to BE
- size_t char_length = length / sizeof(UChar32);
- WTF::Vector<UChar32> utf32be(char_length);
- const UChar32* utf32le = static_cast<const UChar32*>(text);
- for (size_t i = 0; i < char_length; ++i)
- utf32be[i] = base::ByteSwap(utf32le[i]);
- utf16 = icu::UnicodeString::fromUTF32(utf32be.data(),
- static_cast<int32_t>(byte_length));
-#else
- utf16 = icu::UnicodeString::fromUTF32(reinterpret_cast<const UChar32*>(text),
- static_cast<int32_t>(byte_length));
-#endif
- return String(icu::toUCharPtr(utf16.getBuffer()),
- static_cast<unsigned>(utf16.length()));
-}
-
-String StringForText(const void* text,
- size_t byte_length,
- const SkPaint& paint) {
- SkPaint::TextEncoding encoding = paint.getTextEncoding();
- switch (encoding) {
- case SkPaint::kUTF8_TextEncoding:
- return WTF::TextEncoding("UTF-8").Decode(
- reinterpret_cast<const char*>(text), byte_length);
- case SkPaint::kUTF16_TextEncoding:
- return WTF::TextEncoding("UTF-16LE")
- .Decode(reinterpret_cast<const char*>(text), byte_length);
- case SkPaint::kUTF32_TextEncoding:
- return StringForUTF32LEText(text, byte_length);
- case SkPaint::kGlyphID_TextEncoding: {
- WTF::Vector<SkUnichar> data_vector(byte_length / 2);
- SkUnichar* text_data = data_vector.data();
- paint.glyphsToUnichars(static_cast<const uint16_t*>(text),
- byte_length / 2, text_data);
- return StringForUTF32LEText(text, byte_length);
- }
- default:
- NOTREACHED();
- return "?";
- }
-}
-
} // namespace
class AutoLogger
@@ -725,48 +621,6 @@ void LoggingCanvas::onDrawDRRect(const SkRRect& outer,
this->SkCanvas::onDrawDRRect(outer, inner, paint);
}
-void LoggingCanvas::onDrawText(const void* text,
- size_t byte_length,
- SkScalar x,
- SkScalar y,
- const SkPaint& paint) {
- AutoLogger logger(this);
- JSONObject* params = logger.LogItemWithParams("drawText");
- params->SetString("text", StringForText(text, byte_length, paint));
- params->SetDouble("x", x);
- params->SetDouble("y", y);
- params->SetObject("paint", ObjectForSkPaint(paint));
- this->SkCanvas::onDrawText(text, byte_length, x, y, paint);
-}
-
-void LoggingCanvas::onDrawPosText(const void* text,
- size_t byte_length,
- const SkPoint pos[],
- const SkPaint& paint) {
- AutoLogger logger(this);
- JSONObject* params = logger.LogItemWithParams("drawPosText");
- params->SetString("text", StringForText(text, byte_length, paint));
- size_t points_count = paint.countText(text, byte_length);
- params->SetArray("pos", ArrayForSkPoints(points_count, pos));
- params->SetObject("paint", ObjectForSkPaint(paint));
- this->SkCanvas::onDrawPosText(text, byte_length, pos, paint);
-}
-
-void LoggingCanvas::onDrawPosTextH(const void* text,
- size_t byte_length,
- const SkScalar xpos[],
- SkScalar const_y,
- const SkPaint& paint) {
- AutoLogger logger(this);
- JSONObject* params = logger.LogItemWithParams("drawPosTextH");
- params->SetString("text", StringForText(text, byte_length, paint));
- size_t points_count = paint.countText(text, byte_length);
- params->SetArray("xpos", ArrayForSkScalars(points_count, xpos));
- params->SetDouble("constY", const_y);
- params->SetObject("paint", ObjectForSkPaint(paint));
- this->SkCanvas::onDrawPosTextH(text, byte_length, xpos, const_y, paint);
-}
-
void LoggingCanvas::onDrawTextBlob(const SkTextBlob* blob,
SkScalar x,
SkScalar y,
@@ -870,7 +724,7 @@ SkCanvas::SaveLayerStrategy LoggingCanvas::getSaveLayerStrategy(
params->SetObject("bounds", ObjectForSkRect(*rec.fBounds));
if (rec.fPaint)
params->SetObject("paint", ObjectForSkPaint(*rec.fPaint));
- params->SetString("saveFlags", SaveLayerFlagsToString(rec.fSaveLayerFlags));
+ params->SetInteger("saveFlags", static_cast<int>(rec.fSaveLayerFlags));
return this->SkCanvas::getSaveLayerStrategy(rec);
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.h b/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.h
index eceee7d8ddd..3951bbf51da 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.h
@@ -79,20 +79,6 @@ class LoggingCanvas : public InterceptingCanvasBase {
void onDrawDRRect(const SkRRect& outer,
const SkRRect& inner,
const SkPaint&) override;
- void onDrawText(const void* text,
- size_t byte_length,
- SkScalar x,
- SkScalar y,
- const SkPaint&) override;
- void onDrawPosText(const void* text,
- size_t byte_length,
- const SkPoint pos[],
- const SkPaint&) override;
- void onDrawPosTextH(const void* text,
- size_t byte_length,
- const SkScalar xpos[],
- SkScalar const_y,
- const SkPaint&) override;
void onDrawTextBlob(const SkTextBlob*,
SkScalar x,
SkScalar y,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc b/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc
index 76a59a710b6..da6cd935170 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc
@@ -79,7 +79,7 @@ void MailboxTextureHolder::Sync(MailboxSyncMode mode) {
return;
}
- if (!ContextProviderWrapper() || IsAbandoned())
+ if (!ContextProviderWrapper())
return;
TRACE_EVENT0("blink", "MailboxTextureHolder::Sync");
@@ -129,7 +129,7 @@ bool MailboxTextureHolder::IsValid() const {
// Just assume valid. Potential problem will be detected later.
return true;
}
- return !IsAbandoned() && !!ContextProviderWrapper();
+ return !!ContextProviderWrapper();
}
bool MailboxTextureHolder::IsCrossThread() const {
@@ -141,20 +141,18 @@ MailboxTextureHolder::~MailboxTextureHolder() {
new gpu::SyncToken(sync_token_));
std::unique_ptr<gpu::Mailbox> passed_mailbox(new gpu::Mailbox(mailbox_));
- if (!IsAbandoned()) {
- if (texture_thread_task_runner_ &&
- thread_id_ != Thread::Current()->ThreadId()) {
- PostCrossThreadTask(
- *texture_thread_task_runner_, FROM_HERE,
- CrossThreadBind(&ReleaseTexture, is_converted_from_skia_texture_,
- texture_id_, WTF::Passed(std::move(passed_mailbox)),
- WTF::Passed(ContextProviderWrapper()),
- WTF::Passed(std::move(passed_sync_token))));
- } else {
- ReleaseTexture(is_converted_from_skia_texture_, texture_id_,
- std::move(passed_mailbox), ContextProviderWrapper(),
- std::move(passed_sync_token));
- }
+ if (texture_thread_task_runner_ &&
+ thread_id_ != Thread::Current()->ThreadId()) {
+ PostCrossThreadTask(
+ *texture_thread_task_runner_, FROM_HERE,
+ CrossThreadBind(&ReleaseTexture, is_converted_from_skia_texture_,
+ texture_id_, WTF::Passed(std::move(passed_mailbox)),
+ WTF::Passed(ContextProviderWrapper()),
+ WTF::Passed(std::move(passed_sync_token))));
+ } else {
+ ReleaseTexture(is_converted_from_skia_texture_, texture_id_,
+ std::move(passed_mailbox), ContextProviderWrapper(),
+ std::move(passed_sync_token));
}
texture_id_ = 0u; // invalidate the texture.
diff --git a/chromium/third_party/blink/renderer/platform/graphics/main_thread_mutator_client.cc b/chromium/third_party/blink/renderer/platform/graphics/main_thread_mutator_client.cc
index 378ec6a3fbf..37d3c6c172f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/main_thread_mutator_client.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/main_thread_mutator_client.cc
@@ -15,6 +15,11 @@ MainThreadMutatorClient::MainThreadMutatorClient(
mutator_->SetClient(this);
}
+void MainThreadMutatorClient::SynchronizeAnimatorName(
+ const String& animator_name) {
+ delegate_->SynchronizeAnimatorName(animator_name);
+}
+
void MainThreadMutatorClient::SetMutationUpdate(
std::unique_ptr<AnimationWorkletOutput> output_state) {
delegate_->SetMutationUpdate(std::move(output_state));
diff --git a/chromium/third_party/blink/renderer/platform/graphics/main_thread_mutator_client.h b/chromium/third_party/blink/renderer/platform/graphics/main_thread_mutator_client.h
index 127d8f3da49..f776791ba10 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/main_thread_mutator_client.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/main_thread_mutator_client.h
@@ -20,7 +20,10 @@ class PLATFORM_EXPORT MainThreadMutatorClient : public MutatorClient {
std::unique_ptr<AnimationWorkletMutatorDispatcherImpl>);
~MainThreadMutatorClient() override = default;
+ void SynchronizeAnimatorName(const String& animator_name) override;
void SetMutationUpdate(std::unique_ptr<AnimationWorkletOutput>) override;
+ void NotifyAnimationsPending() override {}
+ void NotifyAnimationsReady() override {}
void SetDelegate(MutatorClient* client);
AnimationWorkletMutatorDispatcherImpl* Mutator() { return mutator_.get(); }
diff --git a/chromium/third_party/blink/renderer/platform/graphics/mutator_client.h b/chromium/third_party/blink/renderer/platform/graphics/mutator_client.h
index b4b5845034f..e83018e168d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/mutator_client.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/mutator_client.h
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/platform/graphics/animation_worklet_mutators_state.h"
#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
@@ -14,7 +15,12 @@ class PLATFORM_EXPORT MutatorClient {
public:
virtual ~MutatorClient() = default;
+ virtual void SynchronizeAnimatorName(const String& animator_name) = 0;
virtual void SetMutationUpdate(std::unique_ptr<AnimationWorkletOutput>) = 0;
+
+ virtual void NotifyAnimationsPending() = 0;
+
+ virtual void NotifyAnimationsReady() = 0;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/README.md b/chromium/third_party/blink/renderer/platform/graphics/paint/README.md
index 26a11012dab..2f2163bceda 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/README.md
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/README.md
@@ -6,18 +6,18 @@ concepts, such as DOM elements and layout objects.
This code is owned by the [paint team][paint-team-site].
-Slimming Paint v2 is currently being implemented. Unlike Slimming Paint v1, SPv2
-represents its paint artifact not as a flat display list, but as a list of
-drawings, and a list of paint chunks, stored together.
+CompositeAfterPaint is currently being implemented. Unlike Slimming Paint v1,
+CompositeAfterPaint represents its paint artifact not as a flat display list,
+but as a list of drawings, and a list of paint chunks, stored together.
-This document explains the SPv2 world as it develops, not the SPv1 world it
-replaces.
+This document explains the CompositeAfterPaint (CAP) world as it develops, not
+the SPv1 world it replaces.
-[paint-team-site]: https://www.chromium.org/developers/paint-team
+[paint-team-site]: https://www.chromium.org/teams/paint-team
## Paint artifact
-The SPv2 [paint artifact](paint_artifact.h) consists of a list of display items
+The CAP [paint artifact](paint_artifact.h) consists of a list of display items
in paint order (ideally mostly or all drawings), partitioned into *paint chunks*
which define certain *paint properties* which affect how the content should be
drawn or composited.
@@ -142,7 +142,7 @@ images.
*** note
It is illegal for there to be two display items with the same ID in a display
item list, except for display items that are marked uncacheable
-(see [DisplayItemCacheSkipper](DisplayItemCacheSkipper.h)).
+(see [DisplayItemCacheSkipper](display_item_cache_skipper.h)).
***
Generally, clients of this code should use stack-allocated recorder classes to
@@ -150,19 +150,19 @@ emit display items to a `PaintController` (using `GraphicsContext`).
### Standalone display items
-#### [DrawingDisplayItem](DrawingDisplayItem.h)
+#### [DrawingDisplayItem](drawing_display_item.h)
Holds a `PaintRecord` which contains the paint operations required to draw some
atom of content.
-#### [ForeignLayerDisplayItem](ForeignLayerDisplayItem.h)
+#### [ForeignLayerDisplayItem](foreign_layer_display_item.h)
Draws an atom of content, but using a `cc::Layer` produced by some agent outside
of the normal Blink paint system (for example, a plugin). Since they always map
to a `cc::Layer`, they are always the only display item in their paint chunk,
and are ineligible for squashing with other layers.
-#### [ScrollHitTestDisplayItem](ScrollHitTestDisplayItem.h)
+#### [ScrollHitTestDisplayItem](scroll_hit_test_display_item.h)
Placeholder for creating a cc::Layer for scrolling in paint order. Hit testing
in the compositor requires both property trees (scroll nodes) and a scrollable
@@ -199,9 +199,9 @@ module using `PaintController` API.
## Paint artifact compositor
-The [`PaintArtifactCompositor`](paint_artifact_compositor.h) is responsible for
-consuming the `PaintArtifact` produced by the `PaintController`, and converting
-it into a form suitable for the compositor to consume.
+[`PaintArtifactCompositor`](../compositing/paint_artifact_compositor.h) is
+responsible for consuming the `PaintArtifact` produced by the `PaintController`,
+and converting it into a form suitable for the compositor to consume.
At present, `PaintArtifactCompositor` creates a cc layer tree, with one layer
for each paint chunk. In the future, it is expected that we will use heuristics
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc
index a79f58d730d..44f0dd87053 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc
@@ -47,7 +47,7 @@ void CullRect::Move(const IntSize& offset) {
CullRect::ApplyTransformResult CullRect::ApplyTransformInternal(
const TransformPaintPropertyNode* transform) {
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
if (const auto* scroll = transform->ScrollNode()) {
rect_.Intersect(scroll->ContainerRect());
if (rect_.IsEmpty())
@@ -80,7 +80,7 @@ CullRect::ApplyTransformResult CullRect::ApplyTransformInternal(
void CullRect::ApplyTransforms(const TransformPaintPropertyNode* source,
const TransformPaintPropertyNode* destination,
const base::Optional<CullRect>& old_cull_rect) {
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
+ DCHECK(RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
Vector<const TransformPaintPropertyNode*> scroll_translations;
for (const auto* t = destination; t != source; t = t->Parent()) {
@@ -115,7 +115,7 @@ void CullRect::ApplyTransforms(const TransformPaintPropertyNode* source,
}
bool CullRect::ChangedEnough(const CullRect& old_cull_rect) const {
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
+ DCHECK(RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
const auto& new_rect = Rect();
const auto& old_rect = old_cull_rect.Rect();
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.h b/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.h
index 73ef85de6e4..375174cf134 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.h
@@ -42,8 +42,8 @@ class PLATFORM_EXPORT CullRect {
// Applies one transform to the cull rect. Before this function is called,
// the cull rect is in the space of the parent the transform node.
- // For SlimmingPaintV2, when the transform is a scroll translation, the cull
- // rect is converted in the following steps:
+ // For CompositeAfterPaint, when the transform is a scroll translation, the
+ // cull rect is converted in the following steps:
// 1. it's clipped by the container rect,
// 2. transformed by inverse of the scroll translation,
// 3. expanded by thousands of pixels for composited scrolling.
@@ -51,13 +51,13 @@ class PLATFORM_EXPORT CullRect {
ApplyTransformInternal(transform);
}
- // For SlimmingPaintV2 only. Applies transforms from |source| (not included)
- // to |destination| (included). For each scroll translation, the cull rect is
- // converted as described in ApplyTransform(). If |old_cull_rect| is provided,
- // and the cull rect converted by the last scroll translation doesn't cover
- // the whole scrolling contents, and the new cull rect doesn't change enough
- // (by hundreds of pixels) from |old_cull_rect|, the cull rect will be set to
- // |old_cull_rect| to avoid repaint on each composited scroll.
+ // For CompositeAfterPaint only. Applies transforms from |source| (not
+ // included) to |destination| (included). For each scroll translation, the
+ // cull rect is converted as described in ApplyTransform(). If |old_cull_rect|
+ // is provided, and the cull rect converted by the last scroll translation
+ // doesn't cover the whole scrolling contents, and the new cull rect doesn't
+ // change enough (by hundreds of pixels) from |old_cull_rect|, the cull rect
+ // will be set to |old_cull_rect| to avoid repaint on each composited scroll.
void ApplyTransforms(const TransformPaintPropertyNode* source,
const TransformPaintPropertyNode* destination,
const base::Optional<CullRect>& old_cull_rect);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect_test.cc
index 40081fb82f9..bff6f12945d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect_test.cc
@@ -114,7 +114,7 @@ TEST_F(CullRectTest, ApplyTransformInfinite) {
}
TEST_F(CullRectTest, ApplyScrollTranslationPartialScrollingContents) {
- ScopedSlimmingPaintV2ForTest spv2(true);
+ ScopedCompositeAfterPaintForTest cap(true);
ScrollPaintPropertyNode::State scroll_state;
scroll_state.container_rect = IntRect(20, 10, 40, 50);
@@ -142,7 +142,7 @@ TEST_F(CullRectTest, ApplyScrollTranslationPartialScrollingContents) {
}
TEST_F(CullRectTest, ApplyScrollTranslationNoIntersectionWithContainerRect) {
- ScopedSlimmingPaintV2ForTest spv2(true);
+ ScopedCompositeAfterPaintForTest cap(true);
ScrollPaintPropertyNode::State scroll_state;
scroll_state.container_rect = IntRect(200, 100, 40, 50);
@@ -157,7 +157,7 @@ TEST_F(CullRectTest, ApplyScrollTranslationNoIntersectionWithContainerRect) {
}
TEST_F(CullRectTest, ApplyScrollTranslationWholeScrollingContents) {
- ScopedSlimmingPaintV2ForTest spv2(true);
+ ScopedCompositeAfterPaintForTest cap(true);
ScrollPaintPropertyNode::State scroll_state;
scroll_state.container_rect = IntRect(20, 10, 40, 50);
@@ -184,7 +184,7 @@ TEST_F(CullRectTest, ApplyScrollTranslationWholeScrollingContents) {
}
TEST_F(CullRectTest, ChangedEnoughEmpty) {
- ScopedSlimmingPaintV2ForTest spv2(true);
+ ScopedCompositeAfterPaintForTest cap(true);
EXPECT_FALSE(ChangedEnough(IntRect(), IntRect()));
EXPECT_FALSE(ChangedEnough(IntRect(1, 1, 0, 0), IntRect(2, 2, 0, 0)));
EXPECT_TRUE(ChangedEnough(IntRect(), IntRect(0, 0, 1, 1)));
@@ -192,7 +192,7 @@ TEST_F(CullRectTest, ChangedEnoughEmpty) {
}
TEST_F(CullRectTest, ChangedNotEnough) {
- ScopedSlimmingPaintV2ForTest spv2(true);
+ ScopedCompositeAfterPaintForTest cap(true);
IntRect old_rect(100, 100, 100, 100);
EXPECT_FALSE(ChangedEnough(old_rect, old_rect));
EXPECT_FALSE(ChangedEnough(old_rect, IntRect(100, 100, 90, 90)));
@@ -201,7 +201,7 @@ TEST_F(CullRectTest, ChangedNotEnough) {
}
TEST_F(CullRectTest, ChangedEnoughScrollScenarios) {
- ScopedSlimmingPaintV2ForTest spv2(true);
+ ScopedCompositeAfterPaintForTest cap(true);
IntRect old_rect(100, 100, 100, 100);
IntRect new_rect(old_rect);
new_rect.Move(500, 0);
@@ -215,7 +215,7 @@ TEST_F(CullRectTest, ChangedEnoughScrollScenarios) {
}
TEST_F(CullRectTest, ApplyTransformsSameTransform) {
- ScopedSlimmingPaintV2ForTest spv2(true);
+ ScopedCompositeAfterPaintForTest cap(true);
auto transform =
CreateTransform(t0(), TransformationMatrix().Translate(1, 2));
CullRect cull_rect1(IntRect(1, 1, 50, 50));
@@ -235,7 +235,7 @@ TEST_F(CullRectTest, ApplyTransformsSameTransform) {
}
TEST_F(CullRectTest, ApplyTransformsWithoutScroll) {
- ScopedSlimmingPaintV2ForTest spv2(true);
+ ScopedCompositeAfterPaintForTest cap(true);
auto t1 = CreateTransform(t0(), TransformationMatrix().Translate(1, 2));
auto t2 = CreateTransform(*t1, TransformationMatrix().Translate(10, 20));
@@ -260,7 +260,7 @@ TEST_F(CullRectTest, ApplyTransformsWithoutScroll) {
}
TEST_F(CullRectTest, ApplyTransformsSingleScrollWholeScrollingContents) {
- ScopedSlimmingPaintV2ForTest spv2(true);
+ ScopedCompositeAfterPaintForTest cap(true);
auto t1 = CreateTransform(t0(), TransformationMatrix().Translate(1, 2));
ScrollPaintPropertyNode::State scroll_state;
@@ -290,7 +290,7 @@ TEST_F(CullRectTest, ApplyTransformsSingleScrollWholeScrollingContents) {
}
TEST_F(CullRectTest, ApplyTransformsSingleScrollPartialScrollingContents) {
- ScopedSlimmingPaintV2ForTest spv2(true);
+ ScopedCompositeAfterPaintForTest cap(true);
auto t1 = CreateTransform(t0(), TransformationMatrix().Translate(1, 2));
ScrollPaintPropertyNode::State scroll_state;
@@ -326,7 +326,7 @@ TEST_F(CullRectTest, ApplyTransformsSingleScrollPartialScrollingContents) {
}
TEST_F(CullRectTest, ApplyTransformsEscapingScroll) {
- ScopedSlimmingPaintV2ForTest spv2(true);
+ ScopedCompositeAfterPaintForTest cap(true);
auto t1 = CreateTransform(t0(), TransformationMatrix().Translate(1, 2));
ScrollPaintPropertyNode::State scroll_state;
@@ -352,7 +352,7 @@ TEST_F(CullRectTest, ApplyTransformsEscapingScroll) {
}
TEST_F(CullRectTest, ApplyTransformsSmallScrollContentsAfterBigScrollContents) {
- ScopedSlimmingPaintV2ForTest spv2(true);
+ ScopedCompositeAfterPaintForTest cap(true);
auto t1 = CreateTransform(t0(), TransformationMatrix().Translate(1, 2));
ScrollPaintPropertyNode::State scroll_state1;
@@ -387,7 +387,7 @@ TEST_F(CullRectTest, ApplyTransformsSmallScrollContentsAfterBigScrollContents) {
}
TEST_F(CullRectTest, ApplyTransformsBigScrollContentsAfterSmallScrollContents) {
- ScopedSlimmingPaintV2ForTest spv2(true);
+ ScopedCompositeAfterPaintForTest cap(true);
auto t1 = CreateTransform(t0(), TransformationMatrix().Translate(1, 2));
ScrollPaintPropertyNode::State scroll_state1;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.cc
index 8077c0e9b3a..9dfd70bbff2 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.cc
@@ -82,7 +82,7 @@ static WTF::String SpecialDrawingTypeAsDebugString(DisplayItem::Type type) {
DEBUG_STRING_CASE(LinkHighlight);
DEBUG_STRING_CASE(ImageAreaFocusRing);
DEBUG_STRING_CASE(OverflowControls);
- DEBUG_STRING_CASE(PageOverlay);
+ DEBUG_STRING_CASE(FrameOverlay);
DEBUG_STRING_CASE(PopupContainerBorder);
DEBUG_STRING_CASE(PopupListBoxBackground);
DEBUG_STRING_CASE(PopupListBoxRow);
@@ -123,6 +123,7 @@ static WTF::String DrawingTypeAsDebugString(DisplayItem::Type type) {
static String ForeignLayerTypeAsDebugString(DisplayItem::Type type) {
switch (type) {
DEBUG_STRING_CASE(ForeignLayerCanvas);
+ DEBUG_STRING_CASE(ForeignLayerDevToolsOverlay);
DEBUG_STRING_CASE(ForeignLayerPlugin);
DEBUG_STRING_CASE(ForeignLayerVideo);
DEBUG_STRING_CASE(ForeignLayerWrapper);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.h
index e0ff93900e2..2c5c6bb2bb2 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.h
@@ -18,14 +18,8 @@
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#endif
-namespace cc {
-class DisplayItemList;
-}
-
namespace blink {
-class GraphicsContext;
-class FloatSize;
enum class PaintPhase;
class PLATFORM_EXPORT DisplayItem {
@@ -75,7 +69,7 @@ class PLATFORM_EXPORT DisplayItem {
kLinkHighlight,
kImageAreaFocusRing,
kOverflowControls,
- kPageOverlay,
+ kFrameOverlay,
kPopupContainerBorder,
kPopupListBoxBackground,
kPopupListBoxRow,
@@ -107,6 +101,7 @@ class PLATFORM_EXPORT DisplayItem {
kForeignLayerFirst,
kForeignLayerCanvas = kForeignLayerFirst,
+ kForeignLayerDevToolsOverlay,
kForeignLayerPlugin,
kForeignLayerVideo,
kForeignLayerWrapper,
@@ -147,11 +142,15 @@ class PLATFORM_EXPORT DisplayItem {
// Some fields are copied from |client|, because we need to access them in
// later paint cycles when |client| may have been destroyed.
- DisplayItem(const DisplayItemClient& client, Type type, size_t derived_size)
+ DisplayItem(const DisplayItemClient& client,
+ Type type,
+ size_t derived_size,
+ bool draws_content = false)
: client_(&client),
visual_rect_(client.VisualRect()),
outset_for_raster_effects_(client.VisualRectOutsetForRasterEffects()),
type_(type),
+ draws_content_(draws_content),
fragment_(0),
is_cacheable_(client.IsCacheable()),
is_tombstone_(false) {
@@ -181,8 +180,6 @@ class PLATFORM_EXPORT DisplayItem {
Id GetId() const { return Id(*client_, GetType(), fragment_); }
- virtual void Replay(GraphicsContext&) const {}
-
const DisplayItemClient& Client() const {
DCHECK(client_);
return *client_;
@@ -216,13 +213,6 @@ class PLATFORM_EXPORT DisplayItem {
fragment_ = fragment;
}
- // Appends this display item to the cc::DisplayItemList, if applicable.
- // |visual_rect_offset| is the offset between the space of the GraphicsLayer
- // which owns the display item and the coordinate space of VisualRect().
- // TODO(wangxianzhu): Remove the parameter for slimming paint v2.
- virtual void AppendToDisplayItemList(const FloatSize& visual_rect_offset,
- cc::DisplayItemList&) const {}
-
// See comments of enum Type for usage of the following macros.
#define DEFINE_CATEGORY_METHODS(Category) \
static constexpr bool Is##Category##Type(Type type) { \
@@ -269,7 +259,7 @@ class PLATFORM_EXPORT DisplayItem {
// DisplayItem.
bool IsTombstone() const { return is_tombstone_; }
- virtual bool DrawsContent() const { return false; }
+ bool DrawsContent() const { return draws_content_; }
#if DCHECK_IS_ON()
static WTF::String TypeAsDebugString(DisplayItem::Type);
@@ -284,18 +274,19 @@ class PLATFORM_EXPORT DisplayItem {
// The default DisplayItem constructor is only used by ContiguousContainer::
// AppendByMoving() where a tombstone DisplayItem is constructed at the source
- // location. Only set is_tombstone_ to true, leaving other fields as-is so
- // that we can get their original values. |visual_rect_| and
- // |outset_for_raster_effects_| are special, see DisplayItemList::
- // AppendByMoving().
- DisplayItem() : is_tombstone_(true) {}
+ // location. Only set draws_content_ to false and is_tombstone_ to true,
+ // leaving other fields as-is so that we can get their original values.
+ // |visual_rect_| and |outset_for_raster_effects_| are special, see
+ // DisplayItemList::AppendByMoving().
+ DisplayItem() : draws_content_(false), is_tombstone_(true) {}
const DisplayItemClient* client_;
FloatRect visual_rect_;
float outset_for_raster_effects_;
- static_assert(kTypeLast < (1 << 8), "DisplayItem::Type should fit in 8 bits");
- unsigned type_ : 8;
+ static_assert(kTypeLast < (1 << 7), "DisplayItem::Type should fit in 7 bits");
+ unsigned type_ : 7;
+ unsigned draws_content_ : 1;
unsigned derived_size_ : 8; // size of the actual derived class
unsigned fragment_ : 14;
unsigned is_cacheable_ : 1;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc
index 97ffe553cd1..771392a0137 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc
@@ -8,13 +8,15 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h"
#include "third_party/blink/renderer/platform/testing/paint_property_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/paint_test_configurations.h"
#include "third_party/blink/renderer/platform/testing/test_paint_artifact.h"
namespace blink {
using ::testing::UnorderedElementsAre;
-class DisplayItemRasterInvalidatorTest : public PaintControllerTestBase {
+class DisplayItemRasterInvalidatorTest : public PaintControllerTestBase,
+ public PaintTestConfigurations {
protected:
DisplayItemRasterInvalidatorTest() : invalidator_([](const IntRect&) {}) {}
@@ -26,6 +28,10 @@ class DisplayItemRasterInvalidatorTest : public PaintControllerTestBase {
// invalidation rects.
IntRect(0, 0, 20000, 20000), PropertyTreeState::Root());
GetPaintController().FinishCycle();
+ if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
+ GetPaintController().ClearPropertyTreeChangedStateTo(
+ PropertyTreeState::Root());
+ }
if (invalidator_.GetTracking())
return invalidator_.GetTracking()->Invalidations();
@@ -37,7 +43,9 @@ class DisplayItemRasterInvalidatorTest : public PaintControllerTestBase {
RasterInvalidator invalidator_;
};
-TEST_F(DisplayItemRasterInvalidatorTest, RemoveItemInMiddle) {
+INSTANTIATE_PAINT_TEST_CASE_P(DisplayItemRasterInvalidatorTest);
+
+TEST_P(DisplayItemRasterInvalidatorTest, RemoveItemInMiddle) {
FakeDisplayItemClient first("first", LayoutRect(100, 100, 300, 300));
FakeDisplayItemClient second("second", LayoutRect(100, 100, 200, 200));
GraphicsContext context(GetPaintController());
@@ -60,7 +68,7 @@ TEST_F(DisplayItemRasterInvalidatorTest, RemoveItemInMiddle) {
invalidator_.SetTracksRasterInvalidations(false);
}
-TEST_F(DisplayItemRasterInvalidatorTest, SwapOrder) {
+TEST_P(DisplayItemRasterInvalidatorTest, SwapOrder) {
FakeDisplayItemClient first("first", LayoutRect(100, 100, 100, 100));
FakeDisplayItemClient second("second", LayoutRect(100, 100, 50, 200));
FakeDisplayItemClient unaffected("unaffected", LayoutRect(300, 300, 10, 10));
@@ -91,7 +99,7 @@ TEST_F(DisplayItemRasterInvalidatorTest, SwapOrder) {
invalidator_.SetTracksRasterInvalidations(false);
}
-TEST_F(DisplayItemRasterInvalidatorTest, SwapOrderAndInvalidateFirst) {
+TEST_P(DisplayItemRasterInvalidatorTest, SwapOrderAndInvalidateFirst) {
FakeDisplayItemClient first("first", LayoutRect(100, 100, 100, 100));
FakeDisplayItemClient second("second", LayoutRect(100, 100, 50, 200));
FakeDisplayItemClient unaffected("unaffected", LayoutRect(300, 300, 10, 10));
@@ -117,7 +125,7 @@ TEST_F(DisplayItemRasterInvalidatorTest, SwapOrderAndInvalidateFirst) {
invalidator_.SetTracksRasterInvalidations(false);
}
-TEST_F(DisplayItemRasterInvalidatorTest, SwapOrderAndInvalidateSecond) {
+TEST_P(DisplayItemRasterInvalidatorTest, SwapOrderAndInvalidateSecond) {
FakeDisplayItemClient first("first", LayoutRect(100, 100, 100, 100));
FakeDisplayItemClient second("second", LayoutRect(100, 100, 50, 200));
FakeDisplayItemClient unaffected("unaffected", LayoutRect(300, 300, 10, 10));
@@ -143,7 +151,7 @@ TEST_F(DisplayItemRasterInvalidatorTest, SwapOrderAndInvalidateSecond) {
invalidator_.SetTracksRasterInvalidations(false);
}
-TEST_F(DisplayItemRasterInvalidatorTest, SwapOrderWithIncrementalInvalidation) {
+TEST_P(DisplayItemRasterInvalidatorTest, SwapOrderWithIncrementalInvalidation) {
FakeDisplayItemClient first("first", LayoutRect(100, 100, 100, 100));
FakeDisplayItemClient second("second", LayoutRect(100, 100, 50, 200));
FakeDisplayItemClient unaffected("unaffected", LayoutRect(300, 300, 10, 10));
@@ -171,7 +179,7 @@ TEST_F(DisplayItemRasterInvalidatorTest, SwapOrderWithIncrementalInvalidation) {
invalidator_.SetTracksRasterInvalidations(false);
}
-TEST_F(DisplayItemRasterInvalidatorTest, NewItemInMiddle) {
+TEST_P(DisplayItemRasterInvalidatorTest, NewItemInMiddle) {
FakeDisplayItemClient first("first", LayoutRect(100, 100, 100, 100));
FakeDisplayItemClient second("second", LayoutRect(100, 100, 50, 200));
FakeDisplayItemClient third("third", LayoutRect(125, 100, 200, 50));
@@ -195,7 +203,7 @@ TEST_F(DisplayItemRasterInvalidatorTest, NewItemInMiddle) {
invalidator_.SetTracksRasterInvalidations(false);
}
-TEST_F(DisplayItemRasterInvalidatorTest, Incremental) {
+TEST_P(DisplayItemRasterInvalidatorTest, Incremental) {
LayoutRect initial_rect(100, 100, 100, 100);
std::unique_ptr<FakeDisplayItemClient> clients[6];
for (size_t i = 0; i < base::size(clients); i++) {
@@ -259,7 +267,7 @@ TEST_F(DisplayItemRasterInvalidatorTest, Incremental) {
invalidator_.SetTracksRasterInvalidations(false);
}
-TEST_F(DisplayItemRasterInvalidatorTest, AddRemoveFirstAndInvalidateSecond) {
+TEST_P(DisplayItemRasterInvalidatorTest, AddRemoveFirstAndInvalidateSecond) {
FakeDisplayItemClient chunk("chunk");
FakeDisplayItemClient first("first", LayoutRect(100, 100, 150, 150));
FakeDisplayItemClient second("second", LayoutRect(200, 200, 50, 50));
@@ -304,7 +312,7 @@ TEST_F(DisplayItemRasterInvalidatorTest, AddRemoveFirstAndInvalidateSecond) {
invalidator_.SetTracksRasterInvalidations(false);
}
-TEST_F(DisplayItemRasterInvalidatorTest, InvalidateFirstAndAddRemoveSecond) {
+TEST_P(DisplayItemRasterInvalidatorTest, InvalidateFirstAndAddRemoveSecond) {
FakeDisplayItemClient first("first", LayoutRect(100, 100, 150, 150));
FakeDisplayItemClient second("second", LayoutRect(200, 200, 50, 50));
GraphicsContext context(GetPaintController());
@@ -351,7 +359,7 @@ TEST_F(DisplayItemRasterInvalidatorTest, InvalidateFirstAndAddRemoveSecond) {
invalidator_.SetTracksRasterInvalidations(false);
}
-TEST_F(DisplayItemRasterInvalidatorTest, SwapOrderWithChildren) {
+TEST_P(DisplayItemRasterInvalidatorTest, SwapOrderWithChildren) {
FakeDisplayItemClient container1("container1",
LayoutRect(100, 100, 100, 100));
FakeDisplayItemClient content1("content1", LayoutRect(100, 100, 50, 200));
@@ -395,7 +403,7 @@ TEST_F(DisplayItemRasterInvalidatorTest, SwapOrderWithChildren) {
invalidator_.SetTracksRasterInvalidations(false);
}
-TEST_F(DisplayItemRasterInvalidatorTest, SwapOrderWithChildrenAndInvalidation) {
+TEST_P(DisplayItemRasterInvalidatorTest, SwapOrderWithChildrenAndInvalidation) {
FakeDisplayItemClient container1("container1",
LayoutRect(100, 100, 100, 100));
FakeDisplayItemClient content1("content1", LayoutRect(100, 100, 50, 200));
@@ -443,7 +451,7 @@ TEST_F(DisplayItemRasterInvalidatorTest, SwapOrderWithChildrenAndInvalidation) {
invalidator_.SetTracksRasterInvalidations(false);
}
-TEST_F(DisplayItemRasterInvalidatorTest, SwapOrderCrossingChunks) {
+TEST_P(DisplayItemRasterInvalidatorTest, SwapOrderCrossingChunks) {
FakeDisplayItemClient container1("container1",
LayoutRect(100, 100, 100, 100));
FakeDisplayItemClient content1("content1", LayoutRect(100, 100, 50, 200));
@@ -492,7 +500,7 @@ TEST_F(DisplayItemRasterInvalidatorTest, SwapOrderCrossingChunks) {
invalidator_.SetTracksRasterInvalidations(false);
}
-TEST_F(DisplayItemRasterInvalidatorTest, SkipCache) {
+TEST_P(DisplayItemRasterInvalidatorTest, SkipCache) {
FakeDisplayItemClient multicol("multicol", LayoutRect(100, 100, 200, 200));
FakeDisplayItemClient content("content", LayoutRect(100, 100, 100, 100));
GraphicsContext context(GetPaintController());
@@ -549,7 +557,7 @@ TEST_F(DisplayItemRasterInvalidatorTest, SkipCache) {
invalidator_.SetTracksRasterInvalidations(false);
}
-TEST_F(DisplayItemRasterInvalidatorTest, PartialSkipCache) {
+TEST_P(DisplayItemRasterInvalidatorTest, PartialSkipCache) {
FakeDisplayItemClient content("content", LayoutRect(100, 100, 250, 250));
GraphicsContext context(GetPaintController());
@@ -581,7 +589,7 @@ TEST_F(DisplayItemRasterInvalidatorTest, PartialSkipCache) {
invalidator_.SetTracksRasterInvalidations(false);
}
-TEST_F(DisplayItemRasterInvalidatorTest, Partial) {
+TEST_P(DisplayItemRasterInvalidatorTest, Partial) {
FakeDisplayItemClient client("client", LayoutRect(100, 100, 300, 300));
GraphicsContext context(GetPaintController());
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc
index a9bf22f86f7..750ac8d93eb 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc
@@ -13,28 +13,6 @@
namespace blink {
-void DrawingDisplayItem::Replay(GraphicsContext& context) const {
- if (record_)
- context.DrawRecord(record_);
-}
-
-void DrawingDisplayItem::AppendToDisplayItemList(
- const FloatSize& visual_rect_offset,
- cc::DisplayItemList& list) const {
- if (record_) {
- list.StartPaint();
- list.push<cc::DrawRecordOp>(record_);
- // Convert visual rect into the GraphicsLayer's coordinate space.
- auto visual_rect = VisualRect();
- visual_rect.Move(-visual_rect_offset);
- list.EndPaintOfUnpaired(EnclosingIntRect(visual_rect));
- }
-}
-
-bool DrawingDisplayItem::DrawsContent() const {
- return record_.get();
-}
-
#if DCHECK_IS_ON()
void DrawingDisplayItem::PropertiesAsJSON(JSONObject& json) const {
DisplayItem::PropertiesAsJSON(json);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h
index dd79922e214..9f3c691c5ff 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h
@@ -33,15 +33,10 @@ class PLATFORM_EXPORT DrawingDisplayItem final : public DisplayItem {
sk_sp<const PaintRecord> record,
bool known_to_be_opaque = false);
- void Replay(GraphicsContext&) const final;
- void AppendToDisplayItemList(const FloatSize& visual_rect_offset,
- cc::DisplayItemList&) const final;
- bool DrawsContent() const final;
-
const sk_sp<const PaintRecord>& GetPaintRecord() const { return record_; }
bool KnownToBeOpaque() const {
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
+ DCHECK(RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
return known_to_be_opaque_;
}
@@ -54,7 +49,7 @@ class PLATFORM_EXPORT DrawingDisplayItem final : public DisplayItem {
sk_sp<const PaintRecord> record_;
- // True if there are no transparent areas. Only used for SlimmingPaintV2.
+ // True if there are no transparent areas. Only used for CompositeAfterPaint.
const bool known_to_be_opaque_;
};
@@ -64,8 +59,11 @@ inline DrawingDisplayItem::DrawingDisplayItem(const DisplayItemClient& client,
Type type,
sk_sp<const PaintRecord> record,
bool known_to_be_opaque)
- : DisplayItem(client, type, sizeof(*this)),
- record_(record && record->size() ? std::move(record) : nullptr),
+ : DisplayItem(client,
+ type,
+ sizeof(*this),
+ /* draws_content*/ record && record->size()),
+ record_(DrawsContent() ? std::move(record) : nullptr),
known_to_be_opaque_(known_to_be_opaque) {
DCHECK(IsDrawingType(type));
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item_test.cc
index 36d2fab5b7c..bde9029d80d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item_test.cc
@@ -45,7 +45,7 @@ static sk_sp<PaintRecord> CreateRectRecordWithTranslate(
return recorder.finishRecordingAsPicture();
}
-TEST_F(DrawingDisplayItemTest, VisualRectAndDrawingBounds) {
+TEST_F(DrawingDisplayItemTest, DrawsContent) {
FloatRect record_bounds(5.5, 6.6, 7.7, 8.8);
LayoutRect drawing_bounds(record_bounds);
client_.SetVisualRect(drawing_bounds);
@@ -53,18 +53,19 @@ TEST_F(DrawingDisplayItemTest, VisualRectAndDrawingBounds) {
DrawingDisplayItem item(client_, DisplayItem::Type::kDocumentBackground,
CreateRectRecord(record_bounds));
EXPECT_EQ(FloatRect(drawing_bounds), item.VisualRect());
+ EXPECT_TRUE(item.DrawsContent());
+}
- auto list1 = base::MakeRefCounted<cc::DisplayItemList>();
- item.AppendToDisplayItemList(FloatSize(), *list1);
- EXPECT_EQ(EnclosingIntRect(drawing_bounds), list1->VisualRectForTesting(0));
-
- FloatSize offset(2.1, 3.6);
- auto list2 = base::MakeRefCounted<cc::DisplayItemList>();
- item.AppendToDisplayItemList(offset, *list2);
- FloatRect visual_rect_with_offset(drawing_bounds);
- visual_rect_with_offset.Move(-offset);
- EXPECT_EQ(EnclosingIntRect(visual_rect_with_offset),
- list2->VisualRectForTesting(0));
+TEST_F(DrawingDisplayItemTest, NullPaintRecord) {
+ DrawingDisplayItem item(client_, DisplayItem::Type::kDocumentBackground,
+ nullptr);
+ EXPECT_FALSE(item.DrawsContent());
+}
+
+TEST_F(DrawingDisplayItemTest, EmptyPaintRecord) {
+ DrawingDisplayItem item(client_, DisplayItem::Type::kDocumentBackground,
+ sk_make_sp<PaintRecord>());
+ EXPECT_FALSE(item.DrawsContent());
}
TEST_F(DrawingDisplayItemTest, Equals) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h
index e51a61abb9f..260e452548f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h
@@ -51,7 +51,7 @@ class PLATFORM_EXPORT DrawingRecorder final {
~DrawingRecorder();
void SetKnownToBeOpaque() {
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
+ DCHECK(RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
known_to_be_opaque_ = true;
}
@@ -60,7 +60,7 @@ class PLATFORM_EXPORT DrawingRecorder final {
const DisplayItemClient& client_;
const DisplayItem::Type type_;
- // True if there are no transparent areas. Only used for SlimmingPaintV2.
+ // True if there are no transparent areas. Only used for CompositeAfterPaint.
bool known_to_be_opaque_;
#if DCHECK_IS_ON()
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h b/chromium/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h
index 09473c1ccdc..636a087901e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h
@@ -44,6 +44,7 @@ class PLATFORM_EXPORT EffectPaintPropertyNode
CompositorFilterOperations filter;
float opacity = 1;
CompositorFilterOperations backdrop_filter;
+ gfx::RectF backdrop_filter_bounds;
SkBlendMode blend_mode = SkBlendMode::kSrcOver;
// === End of effects ===
CompositingReasons direct_compositing_reasons = CompositingReason::kNone;
@@ -56,6 +57,7 @@ class PLATFORM_EXPORT EffectPaintPropertyNode
output_clip == o.output_clip && color_filter == o.color_filter &&
filter == o.filter && opacity == o.opacity &&
backdrop_filter == o.backdrop_filter &&
+ backdrop_filter_bounds == o.backdrop_filter_bounds &&
blend_mode == o.blend_mode &&
direct_compositing_reasons == o.direct_compositing_reasons &&
compositor_element_id == o.compositor_element_id &&
@@ -130,6 +132,10 @@ class PLATFORM_EXPORT EffectPaintPropertyNode
return state_.backdrop_filter;
}
+ const gfx::RectF& BackdropFilterBounds() const {
+ return state_.backdrop_filter_bounds;
+ }
+
bool HasFilterThatMovesPixels() const {
DCHECK(!Parent() || !IsParentAlias());
return state_.filter.HasFilterThatMovesPixels();
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc
index 810f41d8b6c..5e57ee51738 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc
@@ -18,7 +18,9 @@ namespace {
class ForeignLayerDisplayItemClient final : public DisplayItemClient {
public:
ForeignLayerDisplayItemClient(scoped_refptr<cc::Layer> layer)
- : layer_(std::move(layer)) {}
+ : layer_(std::move(layer)) {
+ Invalidate(PaintInvalidationReason::kUncacheable);
+ }
String DebugName() const final { return "ForeignLayer"; }
@@ -41,10 +43,11 @@ ForeignLayerDisplayItem::ForeignLayerDisplayItem(Type type,
: DisplayItem(*new ForeignLayerDisplayItemClient(std::move(layer)),
type,
sizeof(*this)) {
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled() ||
+ DCHECK(RuntimeEnabledFeatures::CompositeAfterPaintEnabled() ||
RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled());
DCHECK(IsForeignLayerType(type));
DCHECK(GetLayer());
+ DCHECK(!IsCacheable());
}
ForeignLayerDisplayItem::~ForeignLayerDisplayItem() {
@@ -55,22 +58,8 @@ cc::Layer* ForeignLayerDisplayItem::GetLayer() const {
return static_cast<const ForeignLayerDisplayItemClient&>(Client()).GetLayer();
}
-void ForeignLayerDisplayItem::Replay(GraphicsContext&) const {
- NOTREACHED();
-}
-
-void ForeignLayerDisplayItem::AppendToDisplayItemList(
- const FloatSize&,
- cc::DisplayItemList&) const {
- NOTREACHED();
-}
-
-bool ForeignLayerDisplayItem::DrawsContent() const {
- return false;
-}
-
bool ForeignLayerDisplayItem::Equals(const DisplayItem& other) const {
- return DisplayItem::Equals(other) &&
+ return GetType() == other.GetType() &&
GetLayer() ==
static_cast<const ForeignLayerDisplayItem&>(other).GetLayer();
}
@@ -84,13 +73,26 @@ void ForeignLayerDisplayItem::PropertiesAsJSON(JSONObject& json) const {
void RecordForeignLayer(GraphicsContext& context,
DisplayItem::Type type,
- scoped_refptr<cc::Layer> layer) {
+ scoped_refptr<cc::Layer> layer,
+ const base::Optional<PropertyTreeState>& properties) {
PaintController& paint_controller = context.GetPaintController();
if (paint_controller.DisplayItemConstructionIsDisabled())
return;
+ // This is like ScopedPaintChunkProperties but uses null id because foreign
+ // layer chunk doesn't need an id nor a client.
+ base::Optional<PropertyTreeState> previous_properties;
+ if (properties) {
+ previous_properties.emplace(paint_controller.CurrentPaintChunkProperties());
+ paint_controller.UpdateCurrentPaintChunkProperties(base::nullopt,
+ *properties);
+ }
paint_controller.CreateAndAppend<ForeignLayerDisplayItem>(type,
std::move(layer));
+ if (properties) {
+ paint_controller.UpdateCurrentPaintChunkProperties(base::nullopt,
+ *previous_properties);
+ }
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h
index 6b42d096d78..19765ba0ce6 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h
@@ -7,6 +7,7 @@
#include "cc/layers/layer.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
+#include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h"
#include "third_party/blink/renderer/platform/platform_export.h"
namespace blink {
@@ -17,7 +18,7 @@ class GraphicsContext;
// A client supplies a layer which can be unwrapped and inserted into the full
// layer tree.
//
-// Before SPv2, this content is not painted, but is instead inserted into the
+// Before CAP, this content is not painted, but is instead inserted into the
// GraphicsLayer tree.
class PLATFORM_EXPORT ForeignLayerDisplayItem final : public DisplayItem {
public:
@@ -27,10 +28,6 @@ class PLATFORM_EXPORT ForeignLayerDisplayItem final : public DisplayItem {
cc::Layer* GetLayer() const;
// DisplayItem
- void Replay(GraphicsContext&) const override;
- void AppendToDisplayItemList(const FloatSize&,
- cc::DisplayItemList&) const override;
- bool DrawsContent() const override;
bool Equals(const DisplayItem&) const override;
#if DCHECK_IS_ON()
void PropertiesAsJSON(JSONObject&) const override;
@@ -39,9 +36,11 @@ class PLATFORM_EXPORT ForeignLayerDisplayItem final : public DisplayItem {
// Records a foreign layer into a GraphicsContext.
// Use this where you would use a recorder class.
-PLATFORM_EXPORT void RecordForeignLayer(GraphicsContext&,
- DisplayItem::Type,
- scoped_refptr<cc::Layer>);
+PLATFORM_EXPORT void RecordForeignLayer(
+ GraphicsContext&,
+ DisplayItem::Type,
+ scoped_refptr<cc::Layer>,
+ const base::Optional<PropertyTreeState>& = base::nullopt);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc
index 24bae6a33f5..914e5dbd380 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc
@@ -233,10 +233,10 @@ bool GeometryMapper::LocalToAncestorVisualRectInternal(
return !rect_to_map.Rect().IsEmpty();
}
- if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
// On SPv1 we may fail when the paint invalidation container creates an
// overflow clip (in ancestor_state) which is not in localState of an
- // out-of-flow positioned descendant. See crbug.com/513108 and layout test
+ // out-of-flow positioned descendant. See crbug.com/513108 and web test
// compositing/overflow/handle-non-ancestor-clip-parent.html (run with
// --enable-prefer-compositing-to-lcd-text) for details.
// Ignore it for SPv1 for now.
@@ -366,7 +366,7 @@ FloatClipRect GeometryMapper::LocalToAncestorClipRectInternal(
}
if (!clip_node) {
success = false;
- if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
// On SPv1 we may fail when the paint invalidation container creates an
// overflow clip (in ancestor_state) which is not in localState of an
// out-of-flow positioned descendant. See crbug.com/513108 and layout
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc
index 4803e356871..4111f356e8a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc
@@ -656,7 +656,7 @@ TEST_P(GeometryMapperTest, SiblingTransformsWithClip) {
// Fails, because the clip of the destination state is not an ancestor of the
// clip of the source state. A known bug in SPv1 would make such query,
// in such case, no clips are applied.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
EXPECT_FALSE(success);
} else {
EXPECT_TRUE(success);
@@ -789,8 +789,8 @@ TEST_P(GeometryMapperTest, ReflectionWithPaintOffset) {
}
TEST_P(GeometryMapperTest, InvertedClip) {
- // This test is invalid for SPv2.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
+ // This test is invalid for CAP.
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
return;
auto clip = CreateClip(c0(), &t0(), FloatRoundedRect(10, 10, 50, 50));
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h
index 51af360bd8f..9fbce5ff645 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h
@@ -11,6 +11,8 @@
namespace blink {
+class GraphicsContext;
+
// A special DisplayItem containing hit test data.
class PLATFORM_EXPORT HitTestDisplayItem final : public DisplayItem {
public:
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
index f4d24ceb026..450676174ee 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
@@ -30,7 +30,8 @@ void ComputeChunkDerivedData(const DisplayItemList& display_items,
chunk.outset_for_raster_effects = std::max(chunk.outset_for_raster_effects,
item.OutsetForRasterEffects());
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled() && item.IsDrawing()) {
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
+ item.IsDrawing()) {
const auto& drawing = static_cast<const DrawingDisplayItem&>(item);
if (drawing.GetPaintRecord() && drawing.KnownToBeOpaque()) {
known_to_be_opaque_region.op(
@@ -100,7 +101,7 @@ void PaintArtifact::AppendDebugDrawing(
const PropertyTreeState& property_tree_state) {
DEFINE_STATIC_LOCAL(DebugDrawingClient, debug_drawing_client, ());
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
+ DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
auto& display_item =
display_item_list_.AllocateAndConstruct<DrawingDisplayItem>(
debug_drawing_client, DisplayItem::kDebugDrawing, std::move(record));
@@ -121,20 +122,17 @@ void PaintArtifact::Replay(cc::PaintCanvas& canvas,
const PropertyTreeState& replay_state,
const IntPoint& offset) const {
TRACE_EVENT0("blink,benchmark", "PaintArtifact::replay");
- scoped_refptr<cc::DisplayItemList> display_item_list =
- PaintChunksToCcLayer::Convert(
- PaintChunks(), replay_state, gfx::Vector2dF(offset.X(), offset.Y()),
- GetDisplayItemList(),
- cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer);
- canvas.drawPicture(display_item_list->ReleaseAsRecord());
+ canvas.drawPicture(GetPaintRecord(replay_state, offset));
}
-DISABLE_CFI_PERF
-void PaintArtifact::AppendToDisplayItemList(const FloatSize& visual_rect_offset,
- cc::DisplayItemList& list) const {
- TRACE_EVENT0("blink,benchmark", "PaintArtifact::AppendToDisplayItemList");
- for (const DisplayItem& item : display_item_list_)
- item.AppendToDisplayItemList(visual_rect_offset, list);
+sk_sp<PaintRecord> PaintArtifact::GetPaintRecord(
+ const PropertyTreeState& replay_state,
+ const IntPoint& offset) const {
+ return PaintChunksToCcLayer::Convert(
+ PaintChunks(), replay_state,
+ gfx::Vector2dF(offset.X(), offset.Y()), GetDisplayItemList(),
+ cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
+ ->ReleaseAsRecord();
}
void PaintArtifact::FinishCycle() {
@@ -142,7 +140,8 @@ void PaintArtifact::FinishCycle() {
// for clearing the property tree changed state at the end of paint instead of
// in FinishCycle. See: LocalFrameView::RunPaintLifecyclePhase.
bool clear_property_tree_changed =
- !RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled();
+ !RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() ||
+ RuntimeEnabledFeatures::CompositeAfterPaintEnabled();
for (auto& chunk : chunks_) {
chunk.client_is_just_created = false;
if (clear_property_tree_changed)
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h
index a4fe34d21c8..8420222bab6 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h
@@ -81,9 +81,8 @@ class PLATFORM_EXPORT PaintArtifact final : public RefCounted<PaintArtifact> {
const PropertyTreeState& replay_state,
const IntPoint& offset = IntPoint()) const;
- // Writes the paint artifact into a cc::DisplayItemList.
- void AppendToDisplayItemList(const FloatSize& visual_rect_offset,
- cc::DisplayItemList& display_list) const;
+ sk_sp<PaintRecord> GetPaintRecord(const PropertyTreeState& replay_state,
+ const IntPoint& offset = IntPoint()) const;
// Called when the caller finishes updating a full document life cycle.
// Will cleanup data (e.g. raster invalidations) that will no longer be used
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h
index 4c8bb2876bc..e60c767797e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h
@@ -37,7 +37,14 @@ struct PLATFORM_EXPORT PaintChunk {
id(id),
properties(props),
is_cacheable(id.client.IsCacheable()),
- client_is_just_created(id.client.IsJustCreated()) {}
+ client_is_just_created(id.client.IsJustCreated()) {
+ // PaintChunk properties should not be null. If these checks are hit,
+ // we may be missing a call to ScopedPaintChunkProperties, see comment in
+ // PaintChunker::IncrementDisplayItemIndex for more information.
+ CHECK(props.Transform());
+ CHECK(props.Clip());
+ CHECK(props.Effect());
+ }
size_t size() const {
DCHECK_GE(end_index, begin_index);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc
index a96ab6fc5fa..b1c253ed477 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc
@@ -33,12 +33,6 @@ class TestChunkerDisplayItem : public DisplayItem {
TestChunkerDisplayItem(const DisplayItemClient& client,
DisplayItem::Type type = DisplayItem::kDrawingFirst)
: DisplayItem(client, type, sizeof(*this)) {}
-
- void Replay(GraphicsContext&) const final { NOTREACHED(); }
- void AppendToDisplayItemList(const FloatSize&,
- cc::DisplayItemList&) const final {
- NOTREACHED();
- }
};
class TestDisplayItemRequiringSeparateChunk : public TestChunkerDisplayItem {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc
index 8af002eccdf..dc1799edeef 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc
@@ -258,12 +258,12 @@ DisplayItem& PaintController::MoveItemFromCurrentListToNewList(size_t index) {
}
void PaintController::InvalidateAll() {
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
+ DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
InvalidateAllInternal();
}
void PaintController::InvalidateAllInternal() {
- // TODO(wangxianzhu): Rename this to InvalidateAllForTesting() for SPv2.
+ // TODO(wangxianzhu): Rename this to InvalidateAllForTesting() for CAP.
// Can only be called during layout/paintInvalidation, not during painting.
DCHECK(new_display_item_list_.IsEmpty());
current_paint_artifact_ = PaintArtifact::Empty();
@@ -272,7 +272,7 @@ void PaintController::InvalidateAllInternal() {
}
bool PaintController::CacheIsAllInvalid() const {
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
+ DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
DCHECK(!cache_is_all_invalid_ || current_paint_artifact_->IsEmpty());
return cache_is_all_invalid_;
}
@@ -588,7 +588,7 @@ size_t PaintController::ApproximateUnsharedMemoryUsage() const {
void PaintController::AppendDebugDrawingAfterCommit(
sk_sp<const PaintRecord> record,
const PropertyTreeState& property_tree_state) {
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
+ DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
DCHECK(new_display_item_list_.IsEmpty());
current_paint_artifact_->AppendDebugDrawing(record, property_tree_state);
}
@@ -718,6 +718,9 @@ void PaintController::CheckDuplicatePaintChunkId(const PaintChunk::Id& id) {
if (IsSkippingCache())
return;
+ if (DisplayItem::IsForeignLayerType(id.type))
+ return;
+
auto it = new_paint_chunk_indices_by_client_.find(&id.client);
if (it != new_paint_chunk_indices_by_client_.end()) {
const auto& indices = it->value;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc
index ad521693437..79d6e952277 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc
@@ -35,10 +35,10 @@ INSTANTIATE_TEST_CASE_P(
PaintControllerTest,
testing::Values(0,
kBlinkGenPropertyTrees,
- kSlimmingPaintV2,
+ kCompositeAfterPaint,
kUnderInvalidationChecking,
kBlinkGenPropertyTrees | kUnderInvalidationChecking,
- kSlimmingPaintV2 | kUnderInvalidationChecking));
+ kCompositeAfterPaint | kUnderInvalidationChecking));
TEST_P(PaintControllerTest, NestedRecorders) {
GraphicsContext context(GetPaintController());
@@ -1453,7 +1453,7 @@ TEST_P(PaintControllerTest, BeginAndEndFrame) {
}
TEST_P(PaintControllerTest, InvalidateAll) {
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
return;
EXPECT_TRUE(GetPaintController().CacheIsAllInvalid());
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_property_node.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_property_node.h
index 46899a783e8..06ec28e1666 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_property_node.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_property_node.h
@@ -12,7 +12,7 @@
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#if DCHECK_IS_ON()
-#include "third_party/blink/renderer/platform/wtf/list_hash_set.h"
+#include "third_party/blink/renderer/platform/wtf/linked_hash_set.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#endif
@@ -208,7 +208,7 @@ class PropertyTreePrinter {
return node;
}
- ListHashSet<const NodeType*> nodes_;
+ LinkedHashSet<const NodeType*> nodes_;
};
template <typename NodeType>
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc
index 239f61dc8c5..2787d1ac80b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc
@@ -48,11 +48,9 @@ PaintRecordBuilder::~PaintRecordBuilder() = default;
sk_sp<PaintRecord> PaintRecordBuilder::EndRecording(
const PropertyTreeState& replay_state) {
- context_->BeginRecording(FloatRect());
paint_controller_->CommitNewDisplayItems();
paint_controller_->FinishCycle();
- paint_controller_->GetPaintArtifact().Replay(*context_, replay_state);
- return context_->EndRecording();
+ return paint_controller_->GetPaintArtifact().GetPaintRecord(replay_state);
}
void PaintRecordBuilder::EndRecording(cc::PaintCanvas& canvas,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h
index 2ddaae4f2f8..22c55278198 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h
@@ -37,6 +37,8 @@ class PLATFORM_EXPORT PaintRecordBuilder final : public DisplayItemClient {
// transient PaintController is used for the duration of the picture building,
// which therefore has no caching. It also resets paint chunk state to
// PropertyTreeState::Root() before beginning to record.
+ // TODO(wangxianzhu): Remove the input PaintController feature for
+ // CompositeAfterPaint.
PaintRecordBuilder(SkMetaData* metadata = nullptr,
GraphicsContext* containing_context = nullptr,
PaintController* = nullptr);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h
index 1ba66b364d8..a80539f573f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h
@@ -31,7 +31,7 @@ struct RasterInvalidationInfo {
// died.
const DisplayItemClient* client = nullptr;
String client_debug_name;
- // For SPv2, this is set in PaintArtifactCompositor when converting chunk
+ // For CAP, this is set in PaintArtifactCompositor when converting chunk
// raster invalidations to cc raster invalidations.
IntRect rect;
PaintInvalidationReason reason = PaintInvalidationReason::kFull;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc
index e33be29d177..b985689d0fe 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc
@@ -160,6 +160,10 @@ void RasterInvalidator::GenerateRasterInvalidations(
mapper.SwitchToChunk(new_chunk);
auto& new_chunk_info = new_chunks_info.emplace_back(*this, mapper, it);
+ // Foreign layers take care of raster invalidation by themselves.
+ if (DisplayItem::IsForeignLayerType(new_chunk.id.type))
+ continue;
+
if (!new_chunk.is_cacheable) {
AddRasterInvalidation(new_chunk_info.bounds_in_layer, new_chunk.id.client,
PaintInvalidationReason::kChunkUncacheable,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator_test.cc
index 13cbaaab2ea..6a7e25139ad 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator_test.cc
@@ -8,13 +8,15 @@
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
#include "third_party/blink/renderer/platform/testing/paint_property_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/paint_test_configurations.h"
#include "third_party/blink/renderer/platform/testing/test_paint_artifact.h"
namespace blink {
static const IntRect kDefaultLayerBounds(-9999, -7777, 18888, 16666);
-class RasterInvalidatorTest : public testing::Test {
+class RasterInvalidatorTest : public testing::Test,
+ public PaintTestConfigurations {
public:
static PropertyTreeState DefaultPropertyTreeState() {
return PropertyTreeState::Root();
@@ -31,6 +33,11 @@ class RasterInvalidatorTest : public testing::Test {
void FinishCycle(PaintArtifact& artifact) {
artifact.FinishCycle();
ClearGeometryMapperCache();
+ if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
+ // See PaintArtifact::FinishCycle() for the reason of doing this.
+ for (auto& chunk : artifact.PaintChunks())
+ chunk.properties.ClearChangedToRoot();
+ }
}
static const Vector<RasterInvalidationInfo> TrackedRasterInvalidations(
@@ -54,6 +61,8 @@ class RasterInvalidatorTest : public testing::Test {
[](const IntRect& rect) {};
};
+INSTANTIATE_PAINT_TEST_CASE_P(RasterInvalidatorTest);
+
#define EXPECT_CHUNK_INVALIDATION_CUSTOM( \
invalidations, index, chunk, expected_reason, layer_offset, mapper) \
do { \
@@ -78,7 +87,7 @@ class RasterInvalidatorTest : public testing::Test {
EXPECT_EQ(PaintInvalidationReason::kIncremental, info.reason); \
} while (false)
-TEST_F(RasterInvalidatorTest, ImplicitFullLayerInvalidation) {
+TEST_P(RasterInvalidatorTest, ImplicitFullLayerInvalidation) {
RasterInvalidator invalidator(kNoopRasterInvalidation);
auto artifact = TestPaintArtifact().Chunk(0).Build();
@@ -94,7 +103,7 @@ TEST_F(RasterInvalidatorTest, ImplicitFullLayerInvalidation) {
invalidator.SetTracksRasterInvalidations(false);
}
-TEST_F(RasterInvalidatorTest, LayerBounds) {
+TEST_P(RasterInvalidatorTest, LayerBounds) {
RasterInvalidator invalidator(kNoopRasterInvalidation);
auto artifact = TestPaintArtifact().Chunk(0).Build();
@@ -122,7 +131,7 @@ TEST_F(RasterInvalidatorTest, LayerBounds) {
FinishCycle(*artifact);
}
-TEST_F(RasterInvalidatorTest, ReorderChunks) {
+TEST_P(RasterInvalidatorTest, ReorderChunks) {
RasterInvalidator invalidator(kNoopRasterInvalidation);
auto artifact = TestPaintArtifact().Chunk(0).Chunk(1).Chunk(2).Build();
invalidator.Generate(artifact, kDefaultLayerBounds,
@@ -150,7 +159,7 @@ TEST_F(RasterInvalidatorTest, ReorderChunks) {
FinishCycle(*new_artifact);
}
-TEST_F(RasterInvalidatorTest, ReorderChunkSubsequences) {
+TEST_P(RasterInvalidatorTest, ReorderChunkSubsequences) {
RasterInvalidator invalidator(kNoopRasterInvalidation);
auto artifact =
TestPaintArtifact().Chunk(0).Chunk(1).Chunk(2).Chunk(3).Chunk(4).Build();
@@ -185,7 +194,7 @@ TEST_F(RasterInvalidatorTest, ReorderChunkSubsequences) {
FinishCycle(*new_artifact);
}
-TEST_F(RasterInvalidatorTest, ChunkAppearAndDisappear) {
+TEST_P(RasterInvalidatorTest, ChunkAppearAndDisappear) {
RasterInvalidator invalidator(kNoopRasterInvalidation);
auto artifact = TestPaintArtifact().Chunk(0).Chunk(1).Chunk(2).Build();
invalidator.Generate(artifact, kDefaultLayerBounds,
@@ -210,7 +219,7 @@ TEST_F(RasterInvalidatorTest, ChunkAppearAndDisappear) {
FinishCycle(*new_artifact);
}
-TEST_F(RasterInvalidatorTest, ChunkAppearAtEnd) {
+TEST_P(RasterInvalidatorTest, ChunkAppearAtEnd) {
RasterInvalidator invalidator(kNoopRasterInvalidation);
auto artifact = TestPaintArtifact().Chunk(0).Build();
invalidator.Generate(artifact, kDefaultLayerBounds,
@@ -230,7 +239,7 @@ TEST_F(RasterInvalidatorTest, ChunkAppearAtEnd) {
FinishCycle(*new_artifact);
}
-TEST_F(RasterInvalidatorTest, UncacheableChunks) {
+TEST_P(RasterInvalidatorTest, UncacheableChunks) {
RasterInvalidator invalidator(kNoopRasterInvalidation);
auto artifact =
TestPaintArtifact().Chunk(0).Chunk(1).Uncacheable().Chunk(2).Build();
@@ -254,7 +263,7 @@ TEST_F(RasterInvalidatorTest, UncacheableChunks) {
}
// Tests the path based on ClipPaintPropertyNode::Changed().
-TEST_F(RasterInvalidatorTest, ClipPropertyChangeRounded) {
+TEST_P(RasterInvalidatorTest, ClipPropertyChangeRounded) {
RasterInvalidator invalidator(kNoopRasterInvalidation);
FloatRoundedRect::Radii radii(FloatSize(1, 2), FloatSize(2, 3),
FloatSize(3, 4), FloatSize(4, 5));
@@ -316,7 +325,7 @@ TEST_F(RasterInvalidatorTest, ClipPropertyChangeRounded) {
}
// Tests the path detecting change of PaintChunkInfo::chunk_to_layer_clip.
-TEST_F(RasterInvalidatorTest, ClipPropertyChangeSimple) {
+TEST_P(RasterInvalidatorTest, ClipPropertyChangeSimple) {
RasterInvalidator invalidator(kNoopRasterInvalidation);
FloatRoundedRect clip_rect(-1000, -1000, 2000, 2000);
auto clip0 = CreateClip(c0(), &t0(), clip_rect);
@@ -385,7 +394,7 @@ TEST_F(RasterInvalidatorTest, ClipPropertyChangeSimple) {
FinishCycle(*artifact);
}
-TEST_F(RasterInvalidatorTest, ClipLocalTransformSpaceChange) {
+TEST_P(RasterInvalidatorTest, ClipLocalTransformSpaceChange) {
RasterInvalidator invalidator(kNoopRasterInvalidation);
auto t1 = CreateTransform(t0(), TransformationMatrix());
@@ -422,7 +431,7 @@ TEST_F(RasterInvalidatorTest, ClipLocalTransformSpaceChange) {
// This is based on ClipLocalTransformSpaceChange, but tests the no-invalidation
// path by letting the clip's LocalTransformSpace be the same as the chunk's
// transform.
-TEST_F(RasterInvalidatorTest, ClipLocalTransformSpaceChangeNoInvalidation) {
+TEST_P(RasterInvalidatorTest, ClipLocalTransformSpaceChangeNoInvalidation) {
RasterInvalidator invalidator(kNoopRasterInvalidation);
auto t1 = CreateTransform(t0(), TransformationMatrix());
@@ -453,7 +462,7 @@ TEST_F(RasterInvalidatorTest, ClipLocalTransformSpaceChangeNoInvalidation) {
FinishCycle(*artifact);
}
-TEST_F(RasterInvalidatorTest, TransformPropertyChange) {
+TEST_P(RasterInvalidatorTest, TransformPropertyChange) {
RasterInvalidator invalidator(kNoopRasterInvalidation);
auto layer_transform = CreateTransform(t0(), TransformationMatrix().Scale(5));
@@ -534,7 +543,7 @@ TEST_F(RasterInvalidatorTest, TransformPropertyChange) {
FinishCycle(*artifact);
}
-TEST_F(RasterInvalidatorTest, TransformPropertyTinyChange) {
+TEST_P(RasterInvalidatorTest, TransformPropertyTinyChange) {
RasterInvalidator invalidator(kNoopRasterInvalidation);
auto layer_transform = CreateTransform(t0(), TransformationMatrix().Scale(5));
@@ -580,7 +589,7 @@ TEST_F(RasterInvalidatorTest, TransformPropertyTinyChange) {
EXPECT_TRUE(invalidated);
}
-TEST_F(RasterInvalidatorTest, TransformPropertyTinyChangeScale) {
+TEST_P(RasterInvalidatorTest, TransformPropertyTinyChangeScale) {
RasterInvalidator invalidator(kNoopRasterInvalidation);
auto layer_transform = CreateTransform(t0(), TransformationMatrix().Scale(5));
@@ -621,7 +630,7 @@ TEST_F(RasterInvalidatorTest, TransformPropertyTinyChangeScale) {
FinishCycle(*artifact);
}
-TEST_F(RasterInvalidatorTest, EffectLocalTransformSpaceChange) {
+TEST_P(RasterInvalidatorTest, EffectLocalTransformSpaceChange) {
RasterInvalidator invalidator(kNoopRasterInvalidation);
auto t1 = CreateTransform(t0(), TransformationMatrix());
@@ -659,7 +668,7 @@ TEST_F(RasterInvalidatorTest, EffectLocalTransformSpaceChange) {
// This is based on EffectLocalTransformSpaceChange, but tests the no-
// invalidation path by letting the effect's LocalTransformSpace be the same as
// the chunk's transform.
-TEST_F(RasterInvalidatorTest, EffectLocalTransformSpaceChangeNoInvalidation) {
+TEST_P(RasterInvalidatorTest, EffectLocalTransformSpaceChangeNoInvalidation) {
RasterInvalidator invalidator(kNoopRasterInvalidation);
auto t1 = CreateTransform(t0(), TransformationMatrix());
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc
index aa79d6d87d4..d5631ea7653 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc
@@ -15,23 +15,13 @@ ScrollHitTestDisplayItem::ScrollHitTestDisplayItem(
const TransformPaintPropertyNode& scroll_offset_node)
: DisplayItem(client, kScrollHitTest, sizeof(*this)),
scroll_offset_node_(scroll_offset_node) {
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
+ DCHECK(RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
// The scroll offset transform node should have an associated scroll node.
DCHECK(scroll_offset_node_.ScrollNode());
}
ScrollHitTestDisplayItem::~ScrollHitTestDisplayItem() = default;
-void ScrollHitTestDisplayItem::Replay(GraphicsContext&) const {
- NOTREACHED();
-}
-
-void ScrollHitTestDisplayItem::AppendToDisplayItemList(
- const FloatSize&,
- cc::DisplayItemList&) const {
- NOTREACHED();
-}
-
bool ScrollHitTestDisplayItem::Equals(const DisplayItem& other) const {
return DisplayItem::Equals(other) &&
&scroll_node() ==
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h
index 4642790e9f8..082b202de2a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h
@@ -34,9 +34,6 @@ class PLATFORM_EXPORT ScrollHitTestDisplayItem final : public DisplayItem {
}
// DisplayItem
- void Replay(GraphicsContext&) const override;
- void AppendToDisplayItemList(const FloatSize&,
- cc::DisplayItemList&) const override;
bool Equals(const DisplayItem&) const override;
#if DCHECK_IS_ON()
void PropertiesAsJSON(JSONObject&) const override;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/path.cc b/chromium/third_party/blink/renderer/platform/graphics/path.cc
index cde993cb82c..f8c90391af9 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/path.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/path.cc
@@ -353,13 +353,10 @@ void Path::AddEllipse(const FloatPoint& p,
float radius_x,
float radius_y,
float start_angle,
- float end_angle,
- bool anticlockwise) {
+ float end_angle) {
DCHECK(EllipseIsRenderable(start_angle, end_angle));
DCHECK_GE(start_angle, 0);
DCHECK_LT(start_angle, kTwoPiFloat);
- DCHECK((anticlockwise && (start_angle - end_angle) >= 0) ||
- (!anticlockwise && (end_angle - start_angle) >= 0));
SkScalar cx = WebCoreFloatToSkScalar(p.X());
SkScalar cy = WebCoreFloatToSkScalar(p.Y());
@@ -400,9 +397,8 @@ void Path::AddEllipse(const FloatPoint& p,
void Path::AddArc(const FloatPoint& p,
float radius,
float start_angle,
- float end_angle,
- bool anticlockwise) {
- AddEllipse(p, radius, radius, start_angle, end_angle, anticlockwise);
+ float end_angle) {
+ AddEllipse(p, radius, radius, start_angle, end_angle);
}
void Path::AddRect(const FloatRect& rect) {
@@ -415,17 +411,14 @@ void Path::AddEllipse(const FloatPoint& p,
float radius_y,
float rotation,
float start_angle,
- float end_angle,
- bool anticlockwise) {
+ float end_angle) {
DCHECK(EllipseIsRenderable(start_angle, end_angle));
DCHECK_GE(start_angle, 0);
DCHECK_LT(start_angle, kTwoPiFloat);
- DCHECK((anticlockwise && (start_angle - end_angle) >= 0) ||
- (!anticlockwise && (end_angle - start_angle) >= 0));
if (!rotation) {
AddEllipse(FloatPoint(p.X(), p.Y()), radius_x, radius_y, start_angle,
- end_angle, anticlockwise);
+ end_angle);
return;
}
@@ -435,8 +428,7 @@ void Path::AddEllipse(const FloatPoint& p,
DCHECK(ellipse_transform.IsInvertible());
AffineTransform inverse_ellipse_transform = ellipse_transform.Inverse();
Transform(inverse_ellipse_transform);
- AddEllipse(FloatPoint::Zero(), radius_x, radius_y, start_angle, end_angle,
- anticlockwise);
+ AddEllipse(FloatPoint::Zero(), radius_x, radius_y, start_angle, end_angle);
Transform(ellipse_transform);
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/path.h b/chromium/third_party/blink/renderer/platform/graphics/path.h
index 395e02313a4..36f374597cc 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/path.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/path.h
@@ -77,6 +77,7 @@ class PLATFORM_EXPORT Path {
Path& operator=(const Path&);
Path& operator=(const SkPath&);
bool operator==(const Path&) const;
+ bool operator!=(const Path& other) const { return !(*this == other); }
bool Contains(const FloatPoint&) const;
bool Contains(const FloatPoint&, WindRule) const;
@@ -144,16 +145,14 @@ class PLATFORM_EXPORT Path {
void AddArc(const FloatPoint&,
float radius,
float start_angle,
- float end_angle,
- bool anticlockwise);
+ float end_angle);
void AddRect(const FloatRect&);
void AddEllipse(const FloatPoint&,
float radius_x,
float radius_y,
float rotation,
float start_angle,
- float end_angle,
- bool anticlockwise);
+ float end_angle);
void AddEllipse(const FloatRect&);
void AddRoundedRect(const FloatRect&, const FloatSize& rounding_radii);
@@ -192,8 +191,7 @@ class PLATFORM_EXPORT Path {
float radius_x,
float radius_y,
float start_angle,
- float end_angle,
- bool anticlockwise);
+ float end_angle);
SkPath StrokePath(const StrokeData&) const;
SkPath path_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/pattern.cc b/chromium/third_party/blink/renderer/platform/graphics/pattern.cc
index 45512c279b0..f38adf2831f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/pattern.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/pattern.cc
@@ -56,14 +56,10 @@ Pattern::Pattern(RepeatMode repeat_mode) : repeat_mode_(repeat_mode) {}
Pattern::~Pattern() = default;
void Pattern::ApplyToFlags(PaintFlags& flags, const SkMatrix& local_matrix) {
- if (!cached_shader_ || IsLocalMatrixChanged(local_matrix))
+ if (!cached_shader_ || local_matrix != cached_shader_->GetLocalMatrix())
cached_shader_ = CreateShader(local_matrix);
flags.setShader(cached_shader_);
}
-bool Pattern::IsLocalMatrixChanged(const SkMatrix& local_matrix) const {
- return local_matrix != cached_shader_->GetLocalMatrix();
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/pattern.h b/chromium/third_party/blink/renderer/platform/graphics/pattern.h
index 821b360ebaa..2f4968c07e2 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/pattern.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/pattern.h
@@ -71,7 +71,6 @@ class PLATFORM_EXPORT Pattern : public RefCounted<Pattern> {
protected:
virtual sk_sp<PaintShader> CreateShader(const SkMatrix&) = 0;
- virtual bool IsLocalMatrixChanged(const SkMatrix&) const;
RepeatMode repeat_mode_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc b/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc
index 67831cef073..be09c5f451a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc
@@ -6,6 +6,7 @@
#include <utility>
+#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/fonts/font.h"
#include "third_party/blink/renderer/platform/fonts/font_description.h"
#include "third_party/blink/renderer/platform/fonts/font_family.h"
@@ -126,7 +127,7 @@ String FormatOriginalResourceSizeBytes(int64_t bytes) {
// Find the smallest unit that can represent |bytes| in 3 digits or less.
// Round up to the next higher unit if possible when it would take 4 digits to
// display the amount, e.g. 1000 KB will be rounded up to 1 MB.
- for (; units < kUnitsNames + (arraysize(kUnitsNames) - 1) &&
+ for (; units < kUnitsNames + (base::size(kUnitsNames) - 1) &&
bytes >= denomenator * 1000;
++units, denomenator *= 1024) {
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/platform_paint_worklet_input.h b/chromium/third_party/blink/renderer/platform/graphics/platform_paint_worklet_input.h
deleted file mode 100644
index 7eb83bad38f..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/platform_paint_worklet_input.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// 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_PLATFORM_GRAPHICS_PLATFORM_PAINT_WORKLET_INPUT_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PLATFORM_PAINT_WORKLET_INPUT_H_
-
-#include "cc/trees/layer_tree_painter.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT PlatformPaintWorkletInput : public cc::PaintWorkletInput {
- public:
- PlatformPaintWorkletInput(const std::string& name,
- const FloatSize& container_size,
- float effective_zoom)
- : name_(name),
- container_size_(container_size),
- effective_zoom_(effective_zoom) {}
-
- ~PlatformPaintWorkletInput() override = default;
-
- const std::string& Name() const { return name_; }
- const FloatSize& ContainerSize() const { return container_size_; }
- float EffectiveZoom() const { return effective_zoom_; }
-
- private:
- std::string name_;
- FloatSize container_size_;
- float effective_zoom_;
- // TODO(crbug.com/895579): add a cross thread style map.
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHIC_PLATFORM_PAINT_WORKLET_INPUT_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc b/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc
index 38cd420db97..34559425faa 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc
@@ -31,11 +31,11 @@
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "build/build_config.h"
+#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_flags.h"
#include "third_party/skia/include/effects/SkCornerPathEffect.h"
#include "third_party/skia/third_party/skcms/skcms.h"
-#include "ui/gfx/icc_profile.h"
#include <algorithm>
#include <cmath>
@@ -319,29 +319,6 @@ SkColor ScaleAlpha(SkColor color, float alpha) {
return SkColorSetA(color, rounded_alpha);
}
-gfx::ColorSpace SkColorSpaceToGfxColorSpace(
- const sk_sp<SkColorSpace> color_space) {
- if (!color_space)
- return gfx::ColorSpace::CreateSRGB();
-
- SkMatrix44 toXYZD50;
- SkColorSpaceTransferFn transfer_fn;
- if (color_space->toXYZD50(&toXYZD50) &&
- color_space->isNumericalTransferFn(&transfer_fn))
- return gfx::ColorSpace::CreateCustom(toXYZD50, transfer_fn);
-
- // Use an intermediate ICC profile to convert the color space data structure.
- // If this fails, we fall back to sRGB.
- sk_sp<SkData> sk_profile = color_space->serialize();
- if (sk_profile) {
- gfx::ICCProfile icc_profile =
- gfx::ICCProfile::FromData(sk_profile->data(), sk_profile->size());
- if (icc_profile.IsValid())
- return icc_profile.GetColorSpace();
- }
- return gfx::ColorSpace::CreateSRGB();
-}
-
bool ApproximatelyEqualSkColorSpaces(sk_sp<SkColorSpace> src_color_space,
sk_sp<SkColorSpace> dst_color_space) {
if ((!src_color_space && dst_color_space) ||
@@ -355,6 +332,12 @@ bool ApproximatelyEqualSkColorSpaces(sk_sp<SkColorSpace> src_color_space,
return skcms_ApproximatelyEqualProfiles(&src_profile, &dst_profile);
}
+SkRect LayoutRectToSkRect(const blink::LayoutRect& rect) {
+ return SkRect::MakeXYWH(SkFloatToScalar(rect.X()), SkFloatToScalar(rect.Y()),
+ SkFloatToScalar(rect.Width()),
+ SkFloatToScalar(rect.Height()));
+}
+
template <typename PrimitiveType>
void DrawFocusRingPrimitive(const PrimitiveType&,
cc::PaintCanvas*,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.h b/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
index 9633ea90b44..7155983ee65 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
@@ -47,6 +47,7 @@
#include "third_party/skia/include/core/SkScalar.h"
namespace blink {
+class LayoutRect;
/**** constants ****/
@@ -56,8 +57,8 @@ enum {
// maximum dimensions, in exchange for a smaller maximum canvas size.
kMaxCanvasArea = 32768 * 8192, // Maximum canvas area in CSS pixels
- // In Skia, we will also limit width/height to 32767.
- kMaxSkiaDim = 32767 // Maximum width/height in CSS pixels.
+ // In Skia, we will also limit width/height to 65535.
+ kMaxSkiaDim = 65535 // Maximum width/height in CSS pixels.
};
bool PLATFORM_EXPORT IsValidImageSize(const IntSize&);
@@ -73,14 +74,12 @@ BlendMode PLATFORM_EXPORT BlendModeFromSkBlendMode(SkBlendMode);
// alpha is in the range [0, 1].
SkColor PLATFORM_EXPORT ScaleAlpha(SkColor, float);
-// Convert a SkColorSpace to a gfx::ColorSpace
-gfx::ColorSpace PLATFORM_EXPORT
-SkColorSpaceToGfxColorSpace(const sk_sp<SkColorSpace>);
-
bool PLATFORM_EXPORT
ApproximatelyEqualSkColorSpaces(sk_sp<SkColorSpace> src_color_space,
sk_sp<SkColorSpace> dst_color_space);
+SkRect PLATFORM_EXPORT LayoutRectToSkRect(const blink::LayoutRect& rect);
+
// Skia has problems when passed infinite, etc floats, filter them to 0.
inline SkScalar WebCoreFloatToSkScalar(float f) {
return SkFloatToScalar(std::isfinite(f) ? f : 0);
@@ -126,13 +125,18 @@ InterpolationQuality ComputeInterpolationQuality(float src_width,
float dest_height,
bool is_data_complete = true);
-// This replicates the old skia behavior when it used to take radius for blur.
-// Now it takes sigma.
-inline SkScalar SkBlurRadiusToSigma(SkScalar radius) {
- SkASSERT(radius >= 0);
- if (radius == 0)
- return 0.0f;
- return 0.288675f * radius + 0.5f;
+// Technically, this is driven by the CSS/Canvas2D specs and unrelated to Skia.
+// It should probably live in the CSS layer, but the notion of a "blur radius"
+// leaks into platform/graphics currently (ideally we should only deal with
+// sigma at this level).
+// TODO(fmalita): find a better home for this helper.
+inline float BlurRadiusToStdDev(float radius) {
+ DCHECK_GE(radius, 0);
+
+ // Per spec, sigma is exactly half the blur radius:
+ // https://www.w3.org/TR/css-backgrounds-3/#shadow-blur
+ // https://html.spec.whatwg.org/multipage/canvas.html#when-shadows-are-drawn
+ return radius * 0.5f;
}
template <typename PrimitiveType>
diff --git a/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils_test.cc b/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils_test.cc
deleted file mode 100644
index 7de98907099..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils_test.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// 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/platform/graphics/skia/skia_utils.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace blink {
-
-class SkiaUtilsTest : public testing::Test {};
-
-// Tests converting a SkColorSpace to a gfx::ColorSpace
-TEST_F(SkiaUtilsTest, SkColorSpaceToGfxColorSpace) {
- std::vector<sk_sp<SkColorSpace>> skia_color_spaces;
-
- SkColorSpace::RenderTargetGamma gammas[] = {
- SkColorSpace::kLinear_RenderTargetGamma,
- SkColorSpace::kSRGB_RenderTargetGamma};
-
- SkColorSpace::Gamut gamuts[] = {
- SkColorSpace::kSRGB_Gamut, SkColorSpace::kAdobeRGB_Gamut,
- SkColorSpace::kDCIP3_D65_Gamut, SkColorSpace::kRec2020_Gamut,
- };
-
- skia_color_spaces.push_back((SkColorSpace::MakeSRGB())->makeColorSpin());
-
- for (unsigned gamma_itr = 0; gamma_itr < 2; gamma_itr++) {
- for (unsigned gamut_itr = 0; gamut_itr < 4; gamut_itr++) {
- skia_color_spaces.push_back(
- SkColorSpace::MakeRGB(gammas[gamma_itr], gamuts[gamut_itr]));
- }
- }
-
- std::vector<gfx::ColorSpace> gfx_color_spaces;
- for (unsigned i = 0; i < skia_color_spaces.size(); i++) {
- gfx::ColorSpace color_space =
- SkColorSpaceToGfxColorSpace(skia_color_spaces[i]);
- ASSERT_TRUE(SkColorSpace::Equals(color_space.ToSkColorSpace().get(),
- skia_color_spaces[i].get()));
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc b/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc
index be22081f4f3..aae49942565 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc
@@ -32,10 +32,6 @@ SkiaTextureHolder::SkiaTextureHolder(
if (!ContextProvider())
return;
- if (texture_holder->IsAbandoned()) {
- Abandon();
- return;
- }
gpu::gles2::GLES2Interface* shared_gl = ContextProvider()->ContextGL();
GrContext* shared_gr_context = ContextProvider()->GetGrContext();
@@ -66,14 +62,8 @@ SkiaTextureHolder::~SkiaTextureHolder() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
-void SkiaTextureHolder::Abandon() {
- if (image_ && image_->getTexture())
- image_->getTexture()->abandon();
- TextureHolder::Abandon();
-}
-
bool SkiaTextureHolder::IsValid() const {
- return !IsAbandoned() && !!ContextProviderWrapper();
+ return !!ContextProviderWrapper();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.h b/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.h
index 9ccde9d01c5..d1c4687957a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.h
@@ -27,7 +27,6 @@ class PLATFORM_EXPORT SkiaTextureHolder final : public TextureHolder {
bool IsValid() const final;
bool CurrentFrameKnownToBeOpaque() final { return image_->isOpaque(); }
sk_sp<SkImage> GetSkImage() final { return image_; }
- void Abandon() final;
// When creating a AcceleratedStaticBitmap from a texture-backed SkImage, this
// function will be called to create a TextureHolder object.
diff --git a/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc b/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc
index 034ac1332ba..8550cb7bf48 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc
@@ -84,6 +84,7 @@ scoped_refptr<StaticBitmapImage> StaticBitmapImage::ConvertToColorSpace(
SkColorType color_type) {
DCHECK(color_space);
sk_sp<SkImage> skia_image = PaintImageForCurrentFrame().GetSkImage();
+
// If we don't need to change the color type, use SkImage::makeColorSpace()
if (skia_image->colorType() == color_type) {
skia_image = skia_image->makeColorSpace(color_space);
@@ -92,23 +93,17 @@ scoped_refptr<StaticBitmapImage> StaticBitmapImage::ConvertToColorSpace(
: nullptr);
}
- // Otherwise, create a surface and draw on that to avoid GPU readback.
- sk_sp<SkColorSpace> src_color_space = skia_image->refColorSpace();
- if (!src_color_space.get())
- src_color_space = SkColorSpace::MakeSRGB();
- sk_sp<SkColorSpace> dst_color_space = color_space;
- if (!dst_color_space.get())
- dst_color_space = SkColorSpace::MakeSRGB();
-
+ // Otherwise we need to create a surface and redraw the image as it is a
+ // different size in memory
SkImageInfo info =
SkImageInfo::Make(skia_image->width(), skia_image->height(), color_type,
- skia_image->alphaType(), dst_color_space);
+ skia_image->alphaType(), color_space);
sk_sp<SkSurface> surface = nullptr;
if (skia_image->isTextureBacked()) {
GrContext* gr = ContextProviderWrapper()->ContextProvider()->GetGrContext();
surface = SkSurface::MakeRenderTarget(gr, SkBudgeted::kNo, info);
} else {
- surface = SkSurface::MakeRaster(info);
+ surface = SkSurface::MakeRaster(info);
}
SkPaint paint;
surface->getCanvas()->drawImage(skia_image, 0, 0, &paint);
@@ -136,7 +131,7 @@ bool StaticBitmapImage::ConvertToArrayBufferContents(
data_size.ValueOrDie() > v8::TypedArray::kMaxLength)
return false;
- size_t alloc_size_in_bytes = rect.Size().Area() * bytes_per_pixel;
+ int alloc_size_in_bytes = data_size.ValueOrDie();
if (!src_image) {
auto data = WTF::ArrayBufferContents::CreateDataHandle(
alloc_size_in_bytes, WTF::ArrayBufferContents::kZeroInitialize);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.h b/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.h
index 28b6537fc87..e52affa47ff 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.h
@@ -65,7 +65,6 @@ class PLATFORM_EXPORT StaticBitmapImage : public Image {
virtual bool HasMailbox() const { return false; }
virtual bool IsValid() const { return true; }
virtual void Transfer() {}
- virtual void Abandon() {}
// Creates a non-gpu copy of the image, or returns this if image is already
// non-gpu.
diff --git a/chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc b/chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc
index 47a08b29157..3a641879c4b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc
@@ -34,7 +34,7 @@ SurfaceLayerBridge::SurfaceLayerBridge(
binding_(this),
surface_embedder_binding_(this),
enable_surface_synchronization_(
- features::IsSurfaceSynchronizationEnabled()),
+ ::features::IsSurfaceSynchronizationEnabled()),
frame_sink_id_(Platform::Current()->GenerateFrameSinkId()),
parent_frame_sink_id_(layer_tree_view ? layer_tree_view->GetFrameSinkId()
: viz::FrameSinkId()) {
@@ -126,18 +126,8 @@ const viz::FrameSinkId& SurfaceLayerBridge::GetFrameSinkId() const {
return frame_sink_id_;
}
-void SurfaceLayerBridge::ClearSurfaceId() {
- current_surface_id_ = viz::SurfaceId();
-
- if (!surface_layer_)
- return;
-
- // We reset the Ids if we lose the context_provider (case: GPU process ended)
- // If we destroyed the surface_layer before that point, we need not update
- // the ids.
- surface_layer_->SetSurfaceId(viz::SurfaceId(),
- cc::DeadlinePolicy::UseDefaultDeadline());
- surface_layer_->SetOldestAcceptableFallback(viz::SurfaceId());
+void SurfaceLayerBridge::ClearObserver() {
+ observer_ = nullptr;
}
void SurfaceLayerBridge::SetContentsOpaque(bool opaque) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.h b/chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.h
index 6874555fd52..341300dba7c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.h
@@ -57,9 +57,9 @@ class PLATFORM_EXPORT SurfaceLayerBridge
// Implementation of WebSurfaceLayerBridge.
cc::Layer* GetCcLayer() const override;
const viz::FrameSinkId& GetFrameSinkId() const override;
- void ClearSurfaceId() override;
void SetContentsOpaque(bool) override;
void CreateSurfaceLayer() override;
+ void ClearObserver() override;
const viz::SurfaceId& GetSurfaceId() const override {
return current_surface_id_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/texture_holder.h b/chromium/third_party/blink/renderer/platform/graphics/texture_holder.h
index def091d1f44..e57624df203 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/texture_holder.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/texture_holder.h
@@ -48,7 +48,6 @@ class PLATFORM_EXPORT TextureHolder {
NOTREACHED();
return nullptr;
}
- virtual void Abandon() { is_abandoned_ = true; } // Overrides must call base.
// Methods that have exactly the same impelmentation for all sub-classes
base::WeakPtr<WebGraphicsContext3DProviderWrapper> ContextProviderWrapper()
@@ -61,7 +60,6 @@ class PLATFORM_EXPORT TextureHolder {
? context_provider_wrapper_->ContextProvider()
: nullptr;
}
- bool IsAbandoned() const { return is_abandoned_; }
protected:
TextureHolder(base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&
@@ -75,7 +73,6 @@ class PLATFORM_EXPORT TextureHolder {
// and that we need to clear the resouces associated with that
// AcceleratedStaticBitmapImage on the original thread.
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper_;
- bool is_abandoned_ = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc b/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
index c20b1272045..32f6060223c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
@@ -8,12 +8,11 @@
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
-#include "cc/paint/filter_operations.h"
-#include "cc/scheduler/video_frame_controller.h"
#include "components/viz/common/features.h"
#include "components/viz/common/resources/resource_id.h"
#include "components/viz/common/resources/returned_resource.h"
#include "media/base/video_frame.h"
+#include "media/base/video_types.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom-blink.h"
#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "third_party/blink/public/platform/interface_provider.h"
@@ -23,14 +22,6 @@
namespace blink {
-namespace {
-
-// Delay to retry getting the context_provider.
-constexpr base::TimeDelta kGetContextProviderRetryTimeout =
- base::TimeDelta::FromMilliseconds(150);
-
-} // namespace
-
VideoFrameSubmitter::VideoFrameSubmitter(
WebContextProviderCallback context_provider_callback,
std::unique_ptr<VideoFrameResourceProvider> resource_provider)
@@ -39,36 +30,90 @@ VideoFrameSubmitter::VideoFrameSubmitter(
resource_provider_(std::move(resource_provider)),
rotation_(media::VIDEO_ROTATION_0),
enable_surface_synchronization_(
- features::IsSurfaceSynchronizationEnabled()),
+ ::features::IsSurfaceSynchronizationEnabled()),
weak_ptr_factory_(this) {
- DETACH_FROM_THREAD(media_thread_checker_);
+ DETACH_FROM_THREAD(thread_checker_);
}
VideoFrameSubmitter::~VideoFrameSubmitter() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (context_provider_)
context_provider_->RemoveObserver(this);
+
+ // Release VideoFrameResourceProvider early since its destruction will make
+ // calls back into this class via the viz::SharedBitmapReporter interface.
+ resource_provider_.reset();
}
-void VideoFrameSubmitter::SetRotation(media::VideoRotation rotation) {
- rotation_ = rotation;
+void VideoFrameSubmitter::StopUsingProvider() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (is_rendering_)
+ StopRendering();
+ video_frame_provider_ = nullptr;
}
-void VideoFrameSubmitter::SetIsOpaque(bool is_opaque) {
- if (is_opaque_ == is_opaque)
+void VideoFrameSubmitter::StartRendering() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(!is_rendering_);
+ is_rendering_ = true;
+
+ if (compositor_frame_sink_)
+ compositor_frame_sink_->SetNeedsBeginFrame(is_rendering_ && ShouldSubmit());
+}
+
+void VideoFrameSubmitter::StopRendering() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(is_rendering_);
+ DCHECK(video_frame_provider_);
+
+ is_rendering_ = false;
+ UpdateSubmissionState();
+}
+
+void VideoFrameSubmitter::DidReceiveFrame() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(video_frame_provider_);
+
+ // DidReceiveFrame is called before rendering has started, as a part of
+ // VideoRendererSink::PaintSingleFrame.
+ if (!is_rendering_)
+ SubmitSingleFrame();
+}
+
+bool VideoFrameSubmitter::IsDrivingFrameUpdates() const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ // We drive frame updates only when we believe that something is consuming
+ // them. This is different than VideoLayer, which drives updates any time
+ // they're in the layer tree.
+ return is_rendering_ && ShouldSubmit();
+}
+
+void VideoFrameSubmitter::Initialize(cc::VideoFrameProvider* provider) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (!provider)
return;
- is_opaque_ = is_opaque;
- UpdateSubmissionStateInternal();
+ DCHECK(!video_frame_provider_);
+ video_frame_provider_ = provider;
+ context_provider_callback_.Run(
+ nullptr, base::BindOnce(&VideoFrameSubmitter::OnReceivedContextProvider,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void VideoFrameSubmitter::SetRotation(media::VideoRotation rotation) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ rotation_ = rotation;
}
void VideoFrameSubmitter::EnableSubmission(
viz::SurfaceId surface_id,
- base::TimeTicks local_surface_id_allocation_time,
- WebFrameSinkDestroyedCallback frame_sink_destroyed_callback) {
+ base::TimeTicks local_surface_id_allocation_time) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
// TODO(lethalantidote): Set these fields earlier in the constructor. Will
// need to construct VideoFrameSubmitter later in order to do this.
frame_sink_id_ = surface_id.frame_sink_id();
- frame_sink_destroyed_callback_ = frame_sink_destroyed_callback;
child_local_surface_id_allocator_.UpdateFromParent(
viz::LocalSurfaceIdAllocation(surface_id.local_surface_id(),
local_surface_id_allocation_time));
@@ -76,110 +121,128 @@ void VideoFrameSubmitter::EnableSubmission(
StartSubmitting();
}
-void VideoFrameSubmitter::UpdateSubmissionState(bool should_submit) {
- should_submit_internal_ = should_submit;
- UpdateSubmissionStateInternal();
+void VideoFrameSubmitter::SetIsSurfaceVisible(bool is_visible) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ is_surface_visible_ = is_visible;
+ UpdateSubmissionState();
+}
+
+void VideoFrameSubmitter::SetIsPageVisible(bool is_visible) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ is_page_visible_ = is_visible;
+ UpdateSubmissionState();
}
void VideoFrameSubmitter::SetForceSubmit(bool force_submit) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
force_submit_ = force_submit;
- UpdateSubmissionStateInternal();
+ UpdateSubmissionState();
}
-void VideoFrameSubmitter::UpdateSubmissionStateInternal() {
- if (compositor_frame_sink_) {
- compositor_frame_sink_->SetNeedsBeginFrame(IsDrivingFrameUpdates());
- if (ShouldSubmit())
- SubmitSingleFrame();
- else if (!frame_size_.IsEmpty())
- SubmitEmptyFrame();
- }
+void VideoFrameSubmitter::OnContextLost() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (binding_.is_bound())
+ binding_.Unbind();
+
+ if (context_provider_)
+ context_provider_->RemoveObserver(this);
+
+ waiting_for_compositor_ack_ = false;
+
+ resource_provider_->OnContextLost();
+
+ // |compositor_frame_sink_| should be reset last.
+ compositor_frame_sink_.reset();
+
+ context_provider_callback_.Run(
+ context_provider_,
+ base::BindOnce(&VideoFrameSubmitter::OnReceivedContextProvider,
+ weak_ptr_factory_.GetWeakPtr()));
}
-void VideoFrameSubmitter::StopUsingProvider() {
- DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
- if (is_rendering_)
- StopRendering();
- video_frame_provider_ = nullptr;
+void VideoFrameSubmitter::DidReceiveCompositorFrameAck(
+ const WTF::Vector<viz::ReturnedResource>& resources) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ ReclaimResources(resources);
+ waiting_for_compositor_ack_ = false;
}
-void VideoFrameSubmitter::StopRendering() {
- DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
- DCHECK(is_rendering_);
- DCHECK(video_frame_provider_);
+void VideoFrameSubmitter::OnBeginFrame(
+ const viz::BeginFrameArgs& args,
+ WTF::HashMap<uint32_t, ::gfx::mojom::blink::PresentationFeedbackPtr>) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ TRACE_EVENT0("media", "VideoFrameSubmitter::OnBeginFrame");
- is_rendering_ = false;
- UpdateSubmissionStateInternal();
-}
+ viz::BeginFrameAck current_begin_frame_ack(args, false);
+ if (args.type == viz::BeginFrameArgs::MISSED) {
+ compositor_frame_sink_->DidNotProduceFrame(current_begin_frame_ack);
+ return;
+ }
-void VideoFrameSubmitter::SubmitSingleFrame() {
- // If we haven't gotten a valid result yet from |context_provider_callback_|
- // |resource_provider_| will remain uninitalized.
- // |video_frame_provider_| may be null if StopUsingProvider has been called,
- // which could happen if the |video_frame_provider_| is destructing while we
- // are waiting for the ContextProvider.
- if (!resource_provider_->IsInitialized() || !video_frame_provider_)
+ // Update the current frame, even if we haven't gotten an ack for a previous
+ // frame yet. That probably signals a dropped frame, and this will let the
+ // provider know that it happened, since we won't PutCurrentFrame this one.
+ // Note that we should DidNotProduceFrame with or without the ack.
+ if (!video_frame_provider_ || !video_frame_provider_->UpdateCurrentFrame(
+ args.frame_time + args.interval,
+ args.frame_time + 2 * args.interval)) {
+ compositor_frame_sink_->DidNotProduceFrame(current_begin_frame_ack);
return;
+ }
- viz::BeginFrameAck current_begin_frame_ack =
- viz::BeginFrameAck::CreateManualAckWithDamage();
scoped_refptr<media::VideoFrame> video_frame =
video_frame_provider_->GetCurrentFrame();
- if (video_frame) {
- base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(base::IgnoreResult(&VideoFrameSubmitter::SubmitFrame),
- weak_ptr_factory_.GetWeakPtr(), current_begin_frame_ack,
- video_frame));
- video_frame_provider_->PutCurrentFrame();
+
+ // We do have a new frame that we could display. See if we're supposed to
+ // actually submit a frame or not, and try to submit one.
+ //
+ // Not submitting a frame when waiting for a previous ack saves memory by
+ // not building up unused remote side resources. See https://crbug.com/830828.
+ //
+ // TODO(dalecurtis): Can |is_rendering_| ever be false here? Presumably if
+ // StopRendering() is called above we will not have gotten a BeginFrame.
+ if (!is_rendering_ || waiting_for_compositor_ack_ ||
+ !SubmitFrame(current_begin_frame_ack, std::move(video_frame))) {
+ compositor_frame_sink_->DidNotProduceFrame(current_begin_frame_ack);
+ return;
}
-}
-bool VideoFrameSubmitter::ShouldSubmit() const {
- return should_submit_internal_ || force_submit_;
-}
+ // We submitted a frame!
-bool VideoFrameSubmitter::IsDrivingFrameUpdates() const {
- // We drive frame updates only when we believe that something is consuming
- // them. This is different than VideoLayer, which drives updates any time
- // they're in the layer tree.
- return is_rendering_ && ShouldSubmit();
+ // We still signal PutCurrentFrame here, rather than on the ack, so that it
+ // lines up with the correct frame. Otherwise, any intervening calls to
+ // OnBeginFrame => UpdateCurrentFrame will cause the put to signal that the
+ // later frame was displayed.
+ video_frame_provider_->PutCurrentFrame();
}
-void VideoFrameSubmitter::DidReceiveFrame() {
- DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
- DCHECK(video_frame_provider_);
-
- // DidReceiveFrame is called before renderering has started, as a part of
- // PaintSingleFrame.
- if (!is_rendering_) {
- SubmitSingleFrame();
- }
+void VideoFrameSubmitter::ReclaimResources(
+ const WTF::Vector<viz::ReturnedResource>& resources) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ resource_provider_->ReceiveReturnsFromParent(
+ WebVector<viz::ReturnedResource>(resources).ReleaseVector());
}
-void VideoFrameSubmitter::StartRendering() {
- DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
- DCHECK(!is_rendering_);
- is_rendering_ = true;
-
- if (compositor_frame_sink_)
- compositor_frame_sink_->SetNeedsBeginFrame(is_rendering_ && ShouldSubmit());
+void VideoFrameSubmitter::DidAllocateSharedBitmap(
+ mojo::ScopedSharedBufferHandle buffer,
+ const viz::SharedBitmapId& id) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(compositor_frame_sink_);
+ compositor_frame_sink_->DidAllocateSharedBitmap(
+ std::move(buffer), SharedBitmapIdToGpuMailboxPtr(id));
}
-void VideoFrameSubmitter::Initialize(cc::VideoFrameProvider* provider) {
- DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
- if (provider) {
- DCHECK(!video_frame_provider_);
- video_frame_provider_ = provider;
- context_provider_callback_.Run(
- nullptr, base::BindOnce(&VideoFrameSubmitter::OnReceivedContextProvider,
- weak_ptr_factory_.GetWeakPtr()));
- }
+void VideoFrameSubmitter::DidDeleteSharedBitmap(const viz::SharedBitmapId& id) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(compositor_frame_sink_);
+ compositor_frame_sink_->DidDeleteSharedBitmap(
+ SharedBitmapIdToGpuMailboxPtr(id));
}
void VideoFrameSubmitter::OnReceivedContextProvider(
bool use_gpu_compositing,
scoped_refptr<viz::ContextProvider> context_provider) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!use_gpu_compositing) {
resource_provider_->Initialize(nullptr, this);
return;
@@ -188,6 +251,10 @@ void VideoFrameSubmitter::OnReceivedContextProvider(
bool has_good_context = false;
while (!has_good_context) {
if (!context_provider) {
+ // Delay to retry getting the context_provider.
+ constexpr base::TimeDelta kGetContextProviderRetryTimeout =
+ base::TimeDelta::FromMilliseconds(150);
+
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(
@@ -217,7 +284,7 @@ void VideoFrameSubmitter::OnReceivedContextProvider(
}
void VideoFrameSubmitter::StartSubmitting() {
- DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(frame_sink_id_.is_valid());
mojom::blink::EmbeddedFrameSinkProviderPtr provider;
@@ -228,21 +295,55 @@ void VideoFrameSubmitter::StartSubmitting() {
binding_.Bind(mojo::MakeRequest(&client));
provider->CreateCompositorFrameSink(
frame_sink_id_, std::move(client),
- mojo::MakeRequest(&compositor_frame_sink_),
- mojo::MakeRequest(&surface_embedder_));
+ mojo::MakeRequest(&compositor_frame_sink_));
+ if (!surface_embedder_.is_bound()) {
+ provider->ConnectToEmbedder(frame_sink_id_,
+ mojo::MakeRequest(&surface_embedder_));
+ } else {
+ GenerateNewSurfaceId();
+ }
compositor_frame_sink_.set_connection_error_handler(base::BindOnce(
&VideoFrameSubmitter::OnContextLost, base::Unretained(this)));
- UpdateSubmissionStateInternal();
+ UpdateSubmissionState();
+}
+
+void VideoFrameSubmitter::UpdateSubmissionState() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (!compositor_frame_sink_)
+ return;
+
+ compositor_frame_sink_->SetNeedsBeginFrame(IsDrivingFrameUpdates());
+
+ // These two calls are very important; they are responsible for significant
+ // memory savings when content is off-screen.
+ //
+ // While off-screen, we do not submit frames (unless |force_submit_| is true),
+ // which prevents GPU resource creation and accumulation on the remote side.
+ // During the transition to off-screen we further send an empty frame with the
+ // intent to evict any resources held for the previous frame. Combined these
+ // optimizations save 30-50% in cc:: resource memory usage.
+ //
+ // See https://crbug.com/829813 and https://crbug.com/829565.
+ if (ShouldSubmit()) {
+ // We don't want to submit when |is_rendering_| because OnBeginFrame() calls
+ // are already driving submissions. We should still submit the empty frame
+ // in the other branch for memory savings.
+ if (!is_rendering_)
+ SubmitSingleFrame();
+ } else if (!frame_size_.IsEmpty()) {
+ SubmitEmptyFrame();
+ }
}
bool VideoFrameSubmitter::SubmitFrame(
const viz::BeginFrameAck& begin_frame_ack,
scoped_refptr<media::VideoFrame> video_frame) {
- TRACE_EVENT0("media", "VideoFrameSubmitter::SubmitFrame");
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(video_frame);
- DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
+ TRACE_EVENT0("media", "VideoFrameSubmitter::SubmitFrame");
+
if (!compositor_frame_sink_ || !ShouldSubmit())
return false;
@@ -252,47 +353,23 @@ bool VideoFrameSubmitter::SubmitFrame(
frame_size = gfx::Size(frame_size.height(), frame_size.width());
}
if (frame_size_ != frame_size) {
- if (!frame_size_.IsEmpty()) {
- child_local_surface_id_allocator_.GenerateId();
- if (enable_surface_synchronization_) {
- surface_embedder_->SetLocalSurfaceId(
- child_local_surface_id_allocator_
- .GetCurrentLocalSurfaceIdAllocation()
- .local_surface_id());
- }
- }
+ if (!frame_size_.IsEmpty())
+ GenerateNewSurfaceId();
frame_size_ = frame_size;
}
- viz::CompositorFrame compositor_frame;
- std::unique_ptr<viz::RenderPass> render_pass = viz::RenderPass::Create();
-
- render_pass->SetNew(1, gfx::Rect(frame_size_), gfx::Rect(frame_size_),
- gfx::Transform());
- render_pass->filters = cc::FilterOperations();
- resource_provider_->AppendQuads(render_pass.get(), video_frame, rotation_,
- is_opaque_);
- compositor_frame.metadata.begin_frame_ack = begin_frame_ack;
- // We don't assume that the ack is marked as having damage. However, we're
- // definitely emitting a CompositorFrame that damages the entire surface.
- compositor_frame.metadata.begin_frame_ack.has_damage = true;
- compositor_frame.metadata.device_scale_factor = 1;
- compositor_frame.metadata.may_contain_video = true;
+ auto compositor_frame =
+ CreateCompositorFrame(begin_frame_ack, std::move(video_frame));
std::vector<viz::ResourceId> resources;
- DCHECK_LE(render_pass->quad_list.size(), 1u);
- if (!render_pass->quad_list.empty()) {
- for (viz::ResourceId resource_id :
- render_pass->quad_list.front()->resources) {
- resources.push_back(resource_id);
- }
+ const auto& quad_list = compositor_frame.render_pass_list.back()->quad_list;
+ if (!quad_list.empty()) {
+ DCHECK_EQ(quad_list.size(), 1u);
+ resources.assign(quad_list.front()->resources.begin(),
+ quad_list.front()->resources.end());
}
resource_provider_->PrepareSendToParent(resources,
&compositor_frame.resource_list);
- compositor_frame.render_pass_list.push_back(std::move(render_pass));
- compositor_frame.metadata.local_surface_id_allocation_time =
- child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation()
- .allocation_time();
// TODO(lethalantidote): Address third/fourth arg in SubmitCompositorFrame.
compositor_frame_sink_->SubmitCompositorFrame(
@@ -306,143 +383,94 @@ bool VideoFrameSubmitter::SubmitFrame(
}
void VideoFrameSubmitter::SubmitEmptyFrame() {
- TRACE_EVENT0("media", "VideoFrameSubmitter::SubmitEmptyFrame");
- DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(compositor_frame_sink_ && !ShouldSubmit());
DCHECK(!frame_size_.IsEmpty());
-
- viz::CompositorFrame compositor_frame;
-
- compositor_frame.metadata.begin_frame_ack =
- viz::BeginFrameAck::CreateManualAckWithDamage();
- compositor_frame.metadata.device_scale_factor = 1;
- compositor_frame.metadata.may_contain_video = true;
- compositor_frame.metadata.local_surface_id_allocation_time =
- child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation()
- .allocation_time();
-
- std::unique_ptr<viz::RenderPass> render_pass = viz::RenderPass::Create();
- render_pass->SetNew(1, gfx::Rect(frame_size_), gfx::Rect(frame_size_),
- gfx::Transform());
- compositor_frame.render_pass_list.push_back(std::move(render_pass));
+ TRACE_EVENT0("media", "VideoFrameSubmitter::SubmitEmptyFrame");
compositor_frame_sink_->SubmitCompositorFrame(
child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation()
.local_surface_id(),
- std::move(compositor_frame), nullptr, 0);
+ CreateCompositorFrame(viz::BeginFrameAck::CreateManualAckWithDamage(),
+ nullptr),
+ nullptr, 0);
waiting_for_compositor_ack_ = true;
}
-void VideoFrameSubmitter::OnBeginFrame(
- const viz::BeginFrameArgs& args,
- WTF::HashMap<uint32_t, ::gfx::mojom::blink::PresentationFeedbackPtr>) {
- TRACE_EVENT0("media", "VideoFrameSubmitter::OnBeginFrame");
- DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
- viz::BeginFrameAck current_begin_frame_ack(args, false);
- if (args.type == viz::BeginFrameArgs::MISSED) {
- compositor_frame_sink_->DidNotProduceFrame(current_begin_frame_ack);
- return;
- }
+void VideoFrameSubmitter::SubmitSingleFrame() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- // Update the current frame, even if we haven't gotten an ack for a previous
- // frame yet. That probably signals a dropped frame, and this will let the
- // provider know that it happened, since we won't PutCurrentFrame this one.
- // Note that we should DidNotProduceFrame with or without the ack.
- if (!video_frame_provider_ || !video_frame_provider_->UpdateCurrentFrame(
- args.frame_time + args.interval,
- args.frame_time + 2 * args.interval)) {
- compositor_frame_sink_->DidNotProduceFrame(current_begin_frame_ack);
+ // If we haven't gotten a valid result yet from |context_provider_callback_|
+ // |resource_provider_| will remain uninitialized.
+ // |video_frame_provider_| may be null if StopUsingProvider has been called,
+ // which could happen if the |video_frame_provider_| is destructing while we
+ // are waiting for the ContextProvider.
+ if (!resource_provider_->IsInitialized() || !video_frame_provider_)
return;
- }
-
- scoped_refptr<media::VideoFrame> video_frame =
- video_frame_provider_->GetCurrentFrame();
- // We do have a new frame that we could display. See if we're supposed to
- // actually submit a frame or not, and try to submit one.
- if (!is_rendering_ || waiting_for_compositor_ack_ ||
- !SubmitFrame(current_begin_frame_ack, std::move(video_frame))) {
- compositor_frame_sink_->DidNotProduceFrame(current_begin_frame_ack);
+ auto video_frame = video_frame_provider_->GetCurrentFrame();
+ if (!video_frame)
return;
- }
- // We submitted a frame!
+ // TODO(dalecurtis): This probably shouldn't be posted since it runs the risk
+ // of having state change out from under it. All call sites into this method
+ // should be from posted tasks so it should be safe to remove the post.
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(base::IgnoreResult(&VideoFrameSubmitter::SubmitFrame),
+ weak_ptr_factory_.GetWeakPtr(),
+ viz::BeginFrameAck::CreateManualAckWithDamage(),
+ std::move(video_frame)));
- // We still signal PutCurrentFrame here, rather than on the ack, so that it
- // lines up with the correct frame. Otherwise, any intervening calls to
- // OnBeginFrame => UpdateCurrentFrame will cause the put to signal that the
- // later frame was displayed.
video_frame_provider_->PutCurrentFrame();
}
-void VideoFrameSubmitter::OnContextLost() {
- // TODO(lethalantidote): This check will be obsolete once other TODO to move
- // field initialization earlier is fulfilled.
- if (frame_sink_destroyed_callback_)
- frame_sink_destroyed_callback_.Run();
-
- if (binding_.is_bound())
- binding_.Unbind();
-
- if (context_provider_) {
- context_provider_->RemoveObserver(this);
- }
- waiting_for_compositor_ack_ = false;
-
- resource_provider_->OnContextLost();
-
- // |compositor_frame_sink_| should be reset last.
- compositor_frame_sink_.reset();
+bool VideoFrameSubmitter::ShouldSubmit() const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ return (is_surface_visible_ && is_page_visible_) || force_submit_;
+}
- context_provider_callback_.Run(
- context_provider_,
- base::BindOnce(&VideoFrameSubmitter::OnReceivedContextProvider,
- weak_ptr_factory_.GetWeakPtr()));
+viz::CompositorFrame VideoFrameSubmitter::CreateCompositorFrame(
+ const viz::BeginFrameAck& begin_frame_ack,
+ scoped_refptr<media::VideoFrame> video_frame) {
+ DCHECK(!frame_size_.IsEmpty());
- // We need to trigger another submit so that surface_id's get propagated
- // correctly. If we don't, we don't get any more signals to update the
- // submission state.
- should_submit_internal_ = true;
-}
+ viz::CompositorFrame compositor_frame;
+ compositor_frame.metadata.begin_frame_ack = begin_frame_ack;
+ compositor_frame.metadata.frame_token = ++next_frame_token_;
-void VideoFrameSubmitter::DidReceiveCompositorFrameAck(
- const WTF::Vector<viz::ReturnedResource>& resources) {
- DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
- ReclaimResources(resources);
+ // We don't assume that the ack is marked as having damage. However, we're
+ // definitely emitting a CompositorFrame that damages the entire surface.
+ compositor_frame.metadata.begin_frame_ack.has_damage = true;
+ compositor_frame.metadata.device_scale_factor = 1;
+ compositor_frame.metadata.may_contain_video = true;
+ compositor_frame.metadata.local_surface_id_allocation_time =
+ child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation()
+ .allocation_time();
- waiting_for_compositor_ack_ = false;
-}
+ auto render_pass = viz::RenderPass::Create();
+ render_pass->SetNew(1, gfx::Rect(frame_size_), gfx::Rect(frame_size_),
+ gfx::Transform());
-void VideoFrameSubmitter::ReclaimResources(
- const WTF::Vector<viz::ReturnedResource>& resources) {
- DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
- WebVector<viz::ReturnedResource> temp_resources = resources;
- std::vector<viz::ReturnedResource> std_resources =
- temp_resources.ReleaseVector();
- resource_provider_->ReceiveReturnsFromParent(std_resources);
-}
+ if (video_frame) {
+ const bool is_opaque = media::IsOpaque(video_frame->format());
+ resource_provider_->AppendQuads(render_pass.get(), std::move(video_frame),
+ rotation_, is_opaque);
+ }
-void VideoFrameSubmitter::DidAllocateSharedBitmap(
- mojo::ScopedSharedBufferHandle buffer,
- const viz::SharedBitmapId& id) {
- DCHECK(compositor_frame_sink_);
- compositor_frame_sink_->DidAllocateSharedBitmap(
- std::move(buffer), SharedBitmapIdToGpuMailboxPtr(id));
+ compositor_frame.render_pass_list.emplace_back(std::move(render_pass));
+ return compositor_frame;
}
-void VideoFrameSubmitter::DidDeleteSharedBitmap(const viz::SharedBitmapId& id) {
- DCHECK(compositor_frame_sink_);
- compositor_frame_sink_->DidDeleteSharedBitmap(
- SharedBitmapIdToGpuMailboxPtr(id));
-}
+void VideoFrameSubmitter::GenerateNewSurfaceId() {
+ // We need a new id in the event of context loss.
+ child_local_surface_id_allocator_.GenerateId();
+ if (!enable_surface_synchronization_)
+ return;
-void VideoFrameSubmitter::SetSurfaceIdForTesting(
- const viz::SurfaceId& surface_id,
- base::TimeTicks allocation_time) {
- frame_sink_id_ = surface_id.frame_sink_id();
- child_local_surface_id_allocator_.UpdateFromParent(
- viz::LocalSurfaceIdAllocation(surface_id.local_surface_id(),
- allocation_time));
+ surface_embedder_->SetLocalSurfaceId(
+ child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation()
+ .local_surface_id());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.h b/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.h
index 0a0f90deece..bc870137ee0 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.h
@@ -28,29 +28,20 @@ namespace blink {
// This single-threaded class facilitates the communication between the media
// stack and browser renderer, providing compositor frames containing video
-// frames and corresponding resources to the |compositor_frame_sink_|. This
-// class has dependencies on classes that use the media thread's OpenGL
-// ContextProvider, and thus, besides construction, should be consistently ran
-// from the same media SingleThreadTaskRunner.
+// frames and corresponding resources to the |compositor_frame_sink_|.
+//
+// This class requires and uses a viz::ContextProvider, and thus, besides
+// construction, must be consistently accessed from the same thread.
class PLATFORM_EXPORT VideoFrameSubmitter
: public WebVideoFrameSubmitter,
public viz::ContextLostObserver,
public viz::SharedBitmapReporter,
public viz::mojom::blink::CompositorFrameSinkClient {
public:
- explicit VideoFrameSubmitter(WebContextProviderCallback,
- std::unique_ptr<VideoFrameResourceProvider>);
-
+ VideoFrameSubmitter(WebContextProviderCallback,
+ std::unique_ptr<VideoFrameResourceProvider>);
~VideoFrameSubmitter() override;
- bool Rendering() { return is_rendering_; }
- cc::VideoFrameProvider* Provider() { return video_frame_provider_; }
- mojo::Binding<viz::mojom::blink::CompositorFrameSinkClient>* Binding() {
- return &binding_;
- }
-
- void OnReceivedContextProvider(bool, scoped_refptr<viz::ContextProvider>);
-
// cc::VideoFrameProvider::Client implementation.
void StopUsingProvider() override;
void StartRendering() override;
@@ -61,11 +52,11 @@ class PLATFORM_EXPORT VideoFrameSubmitter
// WebVideoFrameSubmitter implementation.
void Initialize(cc::VideoFrameProvider*) override;
void SetRotation(media::VideoRotation) override;
- void SetIsOpaque(bool) override;
- void EnableSubmission(viz::SurfaceId,
- base::TimeTicks local_surface_id_allocation_time,
- WebFrameSinkDestroyedCallback) override;
- void UpdateSubmissionState(bool is_visible) override;
+ void EnableSubmission(
+ viz::SurfaceId,
+ base::TimeTicks local_surface_id_allocation_time) override;
+ void SetIsSurfaceVisible(bool is_visible) override;
+ void SetIsPageVisible(bool is_visible) override;
void SetForceSubmit(bool) override;
// viz::ContextLostObserver implementation.
@@ -87,43 +78,50 @@ class PLATFORM_EXPORT VideoFrameSubmitter
const viz::SharedBitmapId&) override;
void DidDeleteSharedBitmap(const viz::SharedBitmapId&) override;
- void SetCompositorFrameSinkPtrForTesting(
- viz::mojom::blink::CompositorFrameSinkPtr* sink) {
- compositor_frame_sink_ = std::move(*sink);
- }
- void SetSurfaceEmbedderPtrForTesting(
- mojom::blink::SurfaceEmbedderPtr embedder) {
- surface_embedder_ = std::move(embedder);
- }
- void SetSurfaceIdForTesting(const viz::SurfaceId&, base::TimeTicks);
-
private:
- FRIEND_TEST_ALL_PREFIXES(VideoFrameSubmitterTest, ContextLostDuringSubmit);
- FRIEND_TEST_ALL_PREFIXES(VideoFrameSubmitterTest,
- ShouldSubmitPreventsSubmission);
- FRIEND_TEST_ALL_PREFIXES(VideoFrameSubmitterTest,
- SetForceSubmitForcesSubmission);
- FRIEND_TEST_ALL_PREFIXES(VideoFrameSubmitterTest,
- FrameSizeChangeUpdatesLocalSurfaceId);
- FRIEND_TEST_ALL_PREFIXES(VideoFrameSubmitterTest,
- StopUsingProviderDuringContextLost);
+ friend class VideoFrameSubmitterTest;
+ // Called during Initialize() and OnContextLost() after a new ContextGL is
+ // requested.
+ void OnReceivedContextProvider(
+ bool use_gpu_compositing,
+ scoped_refptr<viz::ContextProvider> context_provider);
+
+ // Starts submission and calls UpdateSubmissionState(); which may submit.
void StartSubmitting();
- void UpdateSubmissionStateInternal();
+
+ // Sets CompositorFrameSink::SetNeedsBeginFrame() state and submits a frame if
+ // visible or an empty frame if not.
+ void UpdateSubmissionState();
+
// Returns whether a frame was submitted.
bool SubmitFrame(const viz::BeginFrameAck&, scoped_refptr<media::VideoFrame>);
+
+ // SubmitEmptyFrame() is used to force the remote CompositorFrameSink to
+ // release resources for the last submission; saving a significant amount of
+ // memory (~30%) when content goes off-screen. See https://crbug.com/829813.
void SubmitEmptyFrame();
- // Pulls frame and submits it to compositor.
- // Used in cases like PaintSingleFrame, which occurs before video rendering
- // has started to post a poster image, or to submit a final frame before
- // ending rendering.
+ // Pulls frame and submits it to compositor. Used in cases like
+ // DidReceiveFrame(), which occurs before video rendering has started to post
+ // the first frame or to submit a final frame before ending rendering.
void SubmitSingleFrame();
// Return whether the submitter should submit frames based on its current
- // state.
+ // state. It's important to only submit when this is true to save memory. See
+ // comments above and in UpdateSubmissionState().
bool ShouldSubmit() const;
+ // Generates a new surface ID using using |child_local_surface_id_allocator_|.
+ // Called during context loss or during a frame size change.
+ void GenerateNewSurfaceId();
+
+ // Helper method for creating viz::CompositorFrame. If |video_frame| is null
+ // then the frame will be empty.
+ viz::CompositorFrame CreateCompositorFrame(
+ const viz::BeginFrameAck& begin_frame_ack,
+ scoped_refptr<media::VideoFrame> video_frame);
+
cc::VideoFrameProvider* video_frame_provider_ = nullptr;
scoped_refptr<viz::ContextProvider> context_provider_;
viz::mojom::blink::CompositorFrameSinkPtr compositor_frame_sink_;
@@ -131,18 +129,27 @@ class PLATFORM_EXPORT VideoFrameSubmitter
mojo::Binding<viz::mojom::blink::CompositorFrameSinkClient> binding_;
WebContextProviderCallback context_provider_callback_;
std::unique_ptr<VideoFrameResourceProvider> resource_provider_;
- WebFrameSinkDestroyedCallback frame_sink_destroyed_callback_;
bool waiting_for_compositor_ack_ = false;
+ // Current rendering state. Set by StartRendering() and StopRendering().
bool is_rendering_ = false;
- // If we are not on screen, we should not submit.
- bool should_submit_internal_ = false;
- // Whether frames should always be submitted, even if we're not visible.
+
+ // If the surface is not visible within in the current view port, we should
+ // not submit. Not submitting when off-screen saves significant memory.
+ bool is_surface_visible_ = false;
+
+ // Likewise, if the entire page is not visible, we should not submit. Not
+ // submitting in the background causes the VideoFrameProvider to enter a
+ // background rendering mode using lower frequency artificial BeginFrames.
+ bool is_page_visible_ = true;
+
+ // Whether frames should always be submitted, even if we're not visible. Used
+ // by Picture-in-Picture mode to ensure submission occurs even off-screen.
bool force_submit_ = false;
+
// Needs to be initialized in implementation because media isn't a public_dep
// of blink/platform.
media::VideoRotation rotation_;
- bool is_opaque_ = true;
viz::FrameSinkId frame_sink_id_;
@@ -156,8 +163,9 @@ class PLATFORM_EXPORT VideoFrameSubmitter
viz::ChildLocalSurfaceIdAllocator child_local_surface_id_allocator_;
const bool enable_surface_synchronization_;
+ viz::FrameTokenGenerator next_frame_token_;
- THREAD_CHECKER(media_thread_checker_);
+ THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<VideoFrameSubmitter> weak_ptr_factory_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc b/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
index 6ec09248d5b..7f7e3924e14 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
@@ -20,6 +20,8 @@
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom-blink.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/graphics/test/mock_compositor_frame_sink.h"
+#include "third_party/blink/renderer/platform/graphics/test/mock_embedded_frame_sink_provider.h"
#include "third_party/blink/renderer/platform/graphics/video_frame_resource_provider.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -47,12 +49,13 @@ class MockVideoFrameProvider : public cc::VideoFrameProvider {
DISALLOW_COPY_AND_ASSIGN(MockVideoFrameProvider);
};
-class MockCompositorFrameSink : public viz::mojom::blink::CompositorFrameSink {
+class VideoMockCompositorFrameSink
+ : public viz::mojom::blink::CompositorFrameSink {
public:
- MockCompositorFrameSink(
+ VideoMockCompositorFrameSink(
viz::mojom::blink::CompositorFrameSinkRequest* request)
: binding_(this, std::move(*request)) {}
- ~MockCompositorFrameSink() override = default;
+ ~VideoMockCompositorFrameSink() override = default;
const viz::CompositorFrame& last_submitted_compositor_frame() const {
return last_submitted_compositor_frame_;
@@ -101,7 +104,7 @@ class MockCompositorFrameSink : public viz::mojom::blink::CompositorFrameSink {
viz::CompositorFrame last_submitted_compositor_frame_;
- DISALLOW_COPY_AND_ASSIGN(MockCompositorFrameSink);
+ DISALLOW_COPY_AND_ASSIGN(VideoMockCompositorFrameSink);
};
class MockVideoFrameResourceProvider
@@ -145,9 +148,6 @@ class VideoFrameSubmitterTest : public testing::Test {
video_frame_provider_(new StrictMock<MockVideoFrameProvider>()),
context_provider_(viz::TestContextProvider::Create()) {
context_provider_->BindToCurrentThread();
- }
-
- void SetUp() override {
MakeSubmitter();
scoped_task_environment_.RunUntilIdle();
}
@@ -166,28 +166,55 @@ class VideoFrameSubmitterTest : public testing::Test {
viz::mojom::blink::CompositorFrameSinkPtr submitter_sink;
viz::mojom::blink::CompositorFrameSinkRequest request =
mojo::MakeRequest(&submitter_sink);
- sink_ = std::make_unique<StrictMock<MockCompositorFrameSink>>(&request);
+ sink_ =
+ std::make_unique<StrictMock<VideoMockCompositorFrameSink>>(&request);
// By setting the submission state before we set the sink, we can make
// testing easier without having to worry about the first sent frame.
- submitter_->UpdateSubmissionState(true);
- submitter_->SetCompositorFrameSinkPtrForTesting(&submitter_sink);
+ submitter_->SetIsSurfaceVisible(true);
+ submitter_->compositor_frame_sink_ = std::move(submitter_sink);
mojom::blink::SurfaceEmbedderPtr embedder;
mojo::MakeRequest(&embedder);
- submitter_->SetSurfaceEmbedderPtrForTesting(std::move(embedder));
- submitter_->SetSurfaceIdForTesting(
- viz::SurfaceId(
- viz::FrameSinkId(1, 1),
- viz::LocalSurfaceId(
- 11, base::UnguessableToken::Deserialize(0x111111, 0))),
- base::TimeTicks::Now());
+ submitter_->surface_embedder_ = std::move(embedder);
+ auto surface_id = viz::SurfaceId(
+ viz::FrameSinkId(1, 1),
+ viz::LocalSurfaceId(11,
+ base::UnguessableToken::Deserialize(0x111111, 0)));
+ submitter_->frame_sink_id_ = surface_id.frame_sink_id();
+ submitter_->child_local_surface_id_allocator_.UpdateFromParent(
+ viz::LocalSurfaceIdAllocation(surface_id.local_surface_id(),
+ base::TimeTicks::Now()));
+ }
+
+ bool IsRendering() const { return submitter_->is_rendering_; }
+
+ cc::VideoFrameProvider* GetProvider() const {
+ return submitter_->video_frame_provider_;
+ }
+
+ bool ShouldSubmit() const { return submitter_->ShouldSubmit(); }
+
+ void SubmitSingleFrame() { submitter_->SubmitSingleFrame(); }
+
+ const viz::ChildLocalSurfaceIdAllocator& child_local_surface_id_allocator()
+ const {
+ return submitter_->child_local_surface_id_allocator_;
+ }
+
+ gfx::Size frame_size() const { return submitter_->frame_size_; }
+
+ void OnReceivedContextProvider(
+ bool use_gpu_compositing,
+ scoped_refptr<viz::ContextProvider> context_provider) {
+ submitter_->OnReceivedContextProvider(use_gpu_compositing,
+ std::move(context_provider));
}
protected:
base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<base::SimpleTestTickClock> now_src_;
std::unique_ptr<viz::FakeExternalBeginFrameSource> begin_frame_source_;
- std::unique_ptr<StrictMock<MockCompositorFrameSink>> sink_;
+ std::unique_ptr<StrictMock<VideoMockCompositorFrameSink>> sink_;
std::unique_ptr<StrictMock<MockVideoFrameProvider>> video_frame_provider_;
StrictMock<MockVideoFrameResourceProvider>* resource_provider_;
scoped_refptr<viz::TestContextProvider> context_provider_;
@@ -195,23 +222,23 @@ class VideoFrameSubmitterTest : public testing::Test {
};
TEST_F(VideoFrameSubmitterTest, StatRenderingFlipsBits) {
- EXPECT_FALSE(submitter_->Rendering());
+ EXPECT_FALSE(IsRendering());
EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
submitter_->StartRendering();
scoped_task_environment_.RunUntilIdle();
- EXPECT_TRUE(submitter_->Rendering());
+ EXPECT_TRUE(IsRendering());
}
TEST_F(VideoFrameSubmitterTest, StopUsingProviderNullsProvider) {
- EXPECT_FALSE(submitter_->Rendering());
- EXPECT_EQ(video_frame_provider_.get(), submitter_->Provider());
+ EXPECT_FALSE(IsRendering());
+ EXPECT_EQ(video_frame_provider_.get(), GetProvider());
submitter_->StopUsingProvider();
- EXPECT_EQ(nullptr, submitter_->Provider());
+ EXPECT_EQ(nullptr, GetProvider());
}
TEST_F(VideoFrameSubmitterTest,
@@ -221,7 +248,7 @@ TEST_F(VideoFrameSubmitterTest,
submitter_->StartRendering();
scoped_task_environment_.RunUntilIdle();
- EXPECT_TRUE(submitter_->Rendering());
+ EXPECT_TRUE(IsRendering());
EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
.WillOnce(Return(media::VideoFrame::CreateFrame(
@@ -238,7 +265,7 @@ TEST_F(VideoFrameSubmitterTest,
scoped_task_environment_.RunUntilIdle();
- EXPECT_FALSE(submitter_->Rendering());
+ EXPECT_FALSE(IsRendering());
}
TEST_F(VideoFrameSubmitterTest, DidReceiveFrameDoesNothingIfRendering) {
@@ -247,14 +274,14 @@ TEST_F(VideoFrameSubmitterTest, DidReceiveFrameDoesNothingIfRendering) {
submitter_->StartRendering();
scoped_task_environment_.RunUntilIdle();
- EXPECT_TRUE(submitter_->Rendering());
+ EXPECT_TRUE(IsRendering());
submitter_->DidReceiveFrame();
scoped_task_environment_.RunUntilIdle();
}
TEST_F(VideoFrameSubmitterTest, DidReceiveFrameSubmitsFrame) {
- EXPECT_FALSE(submitter_->Rendering());
+ EXPECT_FALSE(IsRendering());
EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
.WillOnce(Return(media::VideoFrame::CreateFrame(
@@ -272,37 +299,27 @@ TEST_F(VideoFrameSubmitterTest, DidReceiveFrameSubmitsFrame) {
TEST_F(VideoFrameSubmitterTest, ShouldSubmitPreventsSubmission) {
EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
- submitter_->UpdateSubmissionState(false);
+ submitter_->SetIsSurfaceVisible(false);
scoped_task_environment_.RunUntilIdle();
- EXPECT_FALSE(submitter_->ShouldSubmit());
+ EXPECT_FALSE(ShouldSubmit());
EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
submitter_->StartRendering();
scoped_task_environment_.RunUntilIdle();
EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
- EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
- .WillOnce(Return(media::VideoFrame::CreateFrame(
- media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
- gfx::Size(8, 8), base::TimeDelta())));
- EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1);
- EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
- EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
- EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
- EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
- submitter_->UpdateSubmissionState(true);
+ submitter_->SetIsSurfaceVisible(true);
scoped_task_environment_.RunUntilIdle();
- EXPECT_TRUE(submitter_->ShouldSubmit());
+ EXPECT_TRUE(ShouldSubmit());
EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
- EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1);
EXPECT_CALL(*video_frame_provider_, GetCurrentFrame()).Times(0);
- submitter_->UpdateSubmissionState(false);
+ submitter_->SetIsSurfaceVisible(false);
scoped_task_environment_.RunUntilIdle();
- EXPECT_FALSE(submitter_->ShouldSubmit());
+ EXPECT_FALSE(ShouldSubmit());
EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
.WillOnce(Return(media::VideoFrame::CreateFrame(
@@ -310,17 +327,17 @@ TEST_F(VideoFrameSubmitterTest, ShouldSubmitPreventsSubmission) {
gfx::Size(8, 8), base::TimeDelta())));
EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
- submitter_->SubmitSingleFrame();
+ SubmitSingleFrame();
}
// Tests that when set to true SetForceSubmit forces frame submissions.
// regardless of the internal submit state.
TEST_F(VideoFrameSubmitterTest, SetForceSubmitForcesSubmission) {
EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
- submitter_->UpdateSubmissionState(false);
+ submitter_->SetIsSurfaceVisible(false);
scoped_task_environment_.RunUntilIdle();
- EXPECT_FALSE(submitter_->ShouldSubmit());
+ EXPECT_FALSE(ShouldSubmit());
EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
.WillOnce(Return(media::VideoFrame::CreateFrame(
@@ -328,7 +345,7 @@ TEST_F(VideoFrameSubmitterTest, SetForceSubmitForcesSubmission) {
gfx::Size(8, 8), base::TimeDelta())));
EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
submitter_->SetForceSubmit(true);
- EXPECT_TRUE(submitter_->ShouldSubmit());
+ EXPECT_TRUE(ShouldSubmit());
EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1);
@@ -340,34 +357,14 @@ TEST_F(VideoFrameSubmitterTest, SetForceSubmitForcesSubmission) {
scoped_task_environment_.RunUntilIdle();
EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
- EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
- .WillOnce(Return(media::VideoFrame::CreateFrame(
- media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
- gfx::Size(8, 8), base::TimeDelta())));
- EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1);
- EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
- EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
- EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
- EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
- submitter_->UpdateSubmissionState(true);
+ submitter_->SetIsSurfaceVisible(true);
scoped_task_environment_.RunUntilIdle();
-
- EXPECT_TRUE(submitter_->ShouldSubmit());
+ EXPECT_TRUE(ShouldSubmit());
EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
- EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1);
- EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
- EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
- .WillOnce(Return(media::VideoFrame::CreateFrame(
- media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
- gfx::Size(8, 8), base::TimeDelta())));
- EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
- EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
- EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
- submitter_->UpdateSubmissionState(false);
+ submitter_->SetIsSurfaceVisible(false);
scoped_task_environment_.RunUntilIdle();
-
- EXPECT_TRUE(submitter_->ShouldSubmit());
+ EXPECT_TRUE(ShouldSubmit());
EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
.WillOnce(Return(media::VideoFrame::CreateFrame(
@@ -375,12 +372,12 @@ TEST_F(VideoFrameSubmitterTest, SetForceSubmitForcesSubmission) {
gfx::Size(8, 8), base::TimeDelta())));
EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
- submitter_->SubmitSingleFrame();
+ SubmitSingleFrame();
}
TEST_F(VideoFrameSubmitterTest, RotationInformationPassedToResourceProvider) {
// Check to see if rotation is communicated pre-rendering.
- EXPECT_FALSE(submitter_->Rendering());
+ EXPECT_FALSE(IsRendering());
submitter_->SetRotation(media::VideoRotation::VIDEO_ROTATION_90);
@@ -462,138 +459,6 @@ TEST_F(VideoFrameSubmitterTest, RotationInformationPassedToResourceProvider) {
scoped_task_environment_.RunUntilIdle();
}
-TEST_F(VideoFrameSubmitterTest, IsOpaquePassedToResourceProvider) {
- // Check to see if is_opaque is communicated pre-rendering.
- EXPECT_FALSE(submitter_->Rendering());
-
- // We submit a frame on opacity change.
- EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
- EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
- .WillOnce(Return(media::VideoFrame::CreateFrame(
- media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
- gfx::Size(8, 8), base::TimeDelta())));
- EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1);
- EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
- EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
- EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
- EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
-
- submitter_->SetIsOpaque(false);
- scoped_task_environment_.RunUntilIdle();
-
- {
- WTF::Vector<viz::ReturnedResource> resources;
- EXPECT_CALL(*resource_provider_, ReceiveReturnsFromParent(_));
- submitter_->DidReceiveCompositorFrameAck(resources);
- }
-
- EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
- .WillOnce(Return(media::VideoFrame::CreateFrame(
- media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
- gfx::Size(8, 8), base::TimeDelta())));
- EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
- EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
- EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, false));
- EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
- EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
-
- submitter_->DidReceiveFrame();
- scoped_task_environment_.RunUntilIdle();
-
- {
- WTF::Vector<viz::ReturnedResource> resources;
- EXPECT_CALL(*resource_provider_, ReceiveReturnsFromParent(_));
- submitter_->DidReceiveCompositorFrameAck(resources);
- }
-
- // Check to see if an update to is_opaque just before rendering is
- // communicated.
- EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
- EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
- .WillOnce(Return(media::VideoFrame::CreateFrame(
- media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
- gfx::Size(8, 8), base::TimeDelta())));
- EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1);
- EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
- EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
- EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
- EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
- submitter_->SetIsOpaque(true);
- scoped_task_environment_.RunUntilIdle();
-
- EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
- submitter_->StartRendering();
- scoped_task_environment_.RunUntilIdle();
-
- {
- WTF::Vector<viz::ReturnedResource> resources;
- EXPECT_CALL(*resource_provider_, ReceiveReturnsFromParent(_));
- submitter_->DidReceiveCompositorFrameAck(resources);
- }
-
- EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame(_, _))
- .WillOnce(Return(true));
- EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
- .WillOnce(Return(media::VideoFrame::CreateFrame(
- media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
- gfx::Size(8, 8), base::TimeDelta())));
- EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
- EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
- EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, true));
- EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
- EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
-
- viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs(
- BEGINFRAME_FROM_HERE, now_src_.get());
- submitter_->OnBeginFrame(args, {});
- scoped_task_environment_.RunUntilIdle();
-
- {
- WTF::Vector<viz::ReturnedResource> resources;
- EXPECT_CALL(*resource_provider_, ReceiveReturnsFromParent(_));
- submitter_->DidReceiveCompositorFrameAck(resources);
- }
-
- // Check to see if changing is_opaque while rendering is handled.
- EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
- EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
- .WillOnce(Return(media::VideoFrame::CreateFrame(
- media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
- gfx::Size(8, 8), base::TimeDelta())));
- EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1);
- EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
- EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
- EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
- EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
-
- submitter_->SetIsOpaque(false);
- scoped_task_environment_.RunUntilIdle();
-
- {
- WTF::Vector<viz::ReturnedResource> resources;
- EXPECT_CALL(*resource_provider_, ReceiveReturnsFromParent(_));
- submitter_->DidReceiveCompositorFrameAck(resources);
- }
-
- EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame(_, _))
- .WillOnce(Return(true));
- EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
- .WillOnce(Return(media::VideoFrame::CreateFrame(
- media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
- gfx::Size(8, 8), base::TimeDelta())));
- EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
- EXPECT_CALL(*video_frame_provider_, PutCurrentFrame());
- EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, false));
- EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
- EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
-
- submitter_->OnBeginFrame(args, {});
- scoped_task_environment_.RunUntilIdle();
-
- // Updating |is_opaque_| with the same value should not cause a frame submit.
- submitter_->SetIsOpaque(false);
-}
-
TEST_F(VideoFrameSubmitterTest, OnBeginFrameSubmitsFrame) {
EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
@@ -718,6 +583,26 @@ TEST_F(VideoFrameSubmitterTest, WaitingForAckPreventsNewFrame) {
scoped_task_environment_.RunUntilIdle();
}
+// Test that after context is lost, the CompositorFrameSink is recreated but the
+// SurfaceEmbedder isn't.
+TEST_F(VideoFrameSubmitterTest, RecreateCompositorFrameSinkAfterContextLost) {
+ MockEmbeddedFrameSinkProvider mock_embedded_frame_sink_provider;
+ mojo::Binding<mojom::blink::EmbeddedFrameSinkProvider>
+ embedded_frame_sink_provider_binding(&mock_embedded_frame_sink_provider);
+ auto override =
+ mock_embedded_frame_sink_provider.CreateScopedOverrideMojoInterface(
+ &embedded_frame_sink_provider_binding);
+
+ EXPECT_CALL(*resource_provider_, Initialize(_, _));
+ EXPECT_CALL(mock_embedded_frame_sink_provider, ConnectToEmbedder(_, _))
+ .Times(0);
+ EXPECT_CALL(mock_embedded_frame_sink_provider, CreateCompositorFrameSink_(_))
+ .Times(1);
+ submitter_->OnContextLost();
+ OnReceivedContextProvider(true, context_provider_);
+ scoped_task_environment_.RunUntilIdle();
+}
+
// Test that no crash happens if the context is lost during a frame submission.
TEST_F(VideoFrameSubmitterTest, ContextLostDuringSubmit) {
EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
@@ -733,7 +618,7 @@ TEST_F(VideoFrameSubmitterTest, ContextLostDuringSubmit) {
// This will post a task that will later call SubmitFrame(). The call will
// happen after OnContextLost().
- submitter_->SubmitSingleFrame();
+ SubmitSingleFrame();
submitter_->OnContextLost();
@@ -765,7 +650,7 @@ TEST_F(VideoFrameSubmitterTest, StopUsingProviderDuringContextLost) {
// OnReceivedContextProvider returns. We don't run the actual function
// because it would overwrite our fake |sink_| with a real one.
- submitter_->SubmitSingleFrame();
+ SubmitSingleFrame();
scoped_task_environment_.RunUntilIdle();
}
@@ -776,14 +661,14 @@ TEST_F(VideoFrameSubmitterTest, StopUsingProviderDuringContextLost) {
TEST_F(VideoFrameSubmitterTest, FrameSizeChangeUpdatesLocalSurfaceId) {
{
viz::LocalSurfaceId local_surface_id =
- submitter_->child_local_surface_id_allocator_
+ child_local_surface_id_allocator()
.GetCurrentLocalSurfaceIdAllocation()
.local_surface_id();
EXPECT_TRUE(local_surface_id.is_valid());
EXPECT_EQ(11u, local_surface_id.parent_sequence_number());
EXPECT_EQ(viz::kInitialChildSequenceNumber,
local_surface_id.child_sequence_number());
- EXPECT_TRUE(submitter_->frame_size_.IsEmpty());
+ EXPECT_TRUE(frame_size().IsEmpty());
}
EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
@@ -801,19 +686,19 @@ TEST_F(VideoFrameSubmitterTest, FrameSizeChangeUpdatesLocalSurfaceId) {
EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
- submitter_->SubmitSingleFrame();
+ SubmitSingleFrame();
scoped_task_environment_.RunUntilIdle();
{
viz::LocalSurfaceId local_surface_id =
- submitter_->child_local_surface_id_allocator_
+ child_local_surface_id_allocator()
.GetCurrentLocalSurfaceIdAllocation()
.local_surface_id();
EXPECT_TRUE(local_surface_id.is_valid());
EXPECT_EQ(11u, local_surface_id.parent_sequence_number());
EXPECT_EQ(viz::kInitialChildSequenceNumber,
local_surface_id.child_sequence_number());
- EXPECT_EQ(gfx::Size(8, 8), submitter_->frame_size_);
+ EXPECT_EQ(gfx::Size(8, 8), frame_size());
}
EXPECT_CALL(*video_frame_provider_, GetCurrentFrame())
@@ -826,19 +711,19 @@ TEST_F(VideoFrameSubmitterTest, FrameSizeChangeUpdatesLocalSurfaceId) {
EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
- submitter_->SubmitSingleFrame();
+ SubmitSingleFrame();
scoped_task_environment_.RunUntilIdle();
{
viz::LocalSurfaceId local_surface_id =
- submitter_->child_local_surface_id_allocator_
+ child_local_surface_id_allocator()
.GetCurrentLocalSurfaceIdAllocation()
.local_surface_id();
EXPECT_TRUE(local_surface_id.is_valid());
EXPECT_EQ(11u, local_surface_id.parent_sequence_number());
EXPECT_EQ(viz::kInitialChildSequenceNumber + 1,
local_surface_id.child_sequence_number());
- EXPECT_EQ(gfx::Size(2, 2), submitter_->frame_size_);
+ EXPECT_EQ(gfx::Size(2, 2), frame_size());
}
}
@@ -846,7 +731,7 @@ TEST_F(VideoFrameSubmitterTest, VideoRotationOutputRect) {
MakeSubmitter();
EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
submitter_->StartRendering();
- EXPECT_TRUE(submitter_->Rendering());
+ EXPECT_TRUE(IsRendering());
gfx::Size coded_size(1280, 720);
gfx::Size natural_size(1280, 1024);
@@ -947,4 +832,30 @@ TEST_F(VideoFrameSubmitterTest, VideoRotationOutputRect) {
}
}
+TEST_F(VideoFrameSubmitterTest, PageVisibilityControlsSubmission) {
+ // Hide the page and ensure no begin frames are issued.
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
+ submitter_->SetIsPageVisible(false);
+ scoped_task_environment_.RunUntilIdle();
+ EXPECT_FALSE(ShouldSubmit());
+
+ // Start rendering, but since page is hidden nothing should start yet.
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
+ submitter_->StartRendering();
+ scoped_task_environment_.RunUntilIdle();
+
+ // Mark the page as visible and confirm frame submission. This should not
+ // submit since we're already rendering.
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
+ submitter_->SetIsPageVisible(true);
+ scoped_task_environment_.RunUntilIdle();
+
+ // Transition back to the page being hidden and ensure begin frames stop.
+ EXPECT_TRUE(ShouldSubmit());
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
+ EXPECT_CALL(*video_frame_provider_, GetCurrentFrame()).Times(0);
+ submitter_->SetIsPageVisible(false);
+ scoped_task_environment_.RunUntilIdle();
+}
+
} // namespace blink