Commit 05dd77e4 authored by Fredrik Söderqvist's avatar Fredrik Söderqvist Committed by Commit Bot

Make SVGFilterPainter::PrepareEffect return FilterData

This makes it possible to discern "no valid filter" from "contents does
not need recording". In turn this makes it possible to skip the
corresponding FinishEffect() call when there's no valid filter.
This allows simplifying FinishEffect() and drop the Abort() method on
SVGFilterRecordingContext.

The call to SVGFilterRecordingContext::BeginContent() is sunk out of
PrepareEffect() and likewise the clearing of the invalidation mask is
hoisted.

Bug: 109224
Change-Id: I440a0d85f93ec0bd0d043a4f3545d793364b9f1c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2105374Reviewed-by: default avatarStephen Chenney <schenney@chromium.org>
Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#750892}
parent 129460b8
......@@ -34,7 +34,8 @@
namespace blink {
ScopedSVGPaintState::~ScopedSVGPaintState() {
if (filter_) {
if (filter_data_) {
DCHECK(filter_);
DCHECK(SVGResourcesCache::CachedResourcesForLayoutObject(object_));
DCHECK(
SVGResourcesCache::CachedResourcesForLayoutObject(object_)->Filter() ==
......@@ -158,23 +159,24 @@ static bool HasReferenceFilterOnly(const ComputedStyle& style) {
bool ScopedSVGPaintState::ApplyFilterIfNecessary(SVGResources* resources) {
if (!resources)
return !HasReferenceFilterOnly(object_.StyleRef());
LayoutSVGResourceFilter* filter = resources->Filter();
if (!filter)
return true;
filter->ClearInvalidationMask();
filter_recording_context_ =
std::make_unique<SVGFilterRecordingContext>(GetPaintInfo().context);
filter_ = filter;
GraphicsContext* filter_context = SVGFilterPainter(*filter).PrepareEffect(
object_, *filter_recording_context_);
if (!filter_context)
filter_data_ = SVGFilterPainter(*filter).PrepareEffect(object_);
// If we have no filter data (== the filter was invalid) or if we
// don't need to update the source graphics, we can short-circuit
// here.
if (!filter_data_ || !filter_data_->ContentNeedsUpdate())
return false;
// Because the filter needs to cache its contents we replace the context
// during filtering with the filter's context.
GraphicsContext* filter_context = filter_recording_context_->BeginContent();
filter_paint_info_ =
std::make_unique<PaintInfo>(*filter_context, paint_info_);
// Because we cache the filter contents and do not invalidate on paint
// invalidation rect changes, we need to paint the entire filter region
// so elements outside the initial paint (due to scrolling, etc) paint.
......
......@@ -35,6 +35,7 @@
namespace blink {
class FilterData;
class LayoutObject;
class LayoutSVGResourceFilter;
class LayoutSVGResourceMasker;
......@@ -90,6 +91,7 @@ class ScopedSVGPaintState {
paint_info_(paint_info),
display_item_client_(display_item_client),
filter_(nullptr),
filter_data_(nullptr),
masker_(nullptr) {}
~ScopedSVGPaintState();
......@@ -119,6 +121,7 @@ class ScopedSVGPaintState {
const DisplayItemClient& display_item_client_;
std::unique_ptr<PaintInfo> filter_paint_info_;
LayoutSVGResourceFilter* filter_;
FilterData* filter_data_;
LayoutSVGResourceMasker* masker_;
base::Optional<ClipPathClipper> clip_path_clipper_;
std::unique_ptr<SVGFilterRecordingContext> filter_recording_context_;
......
......@@ -46,12 +46,6 @@ sk_sp<PaintRecord> SVGFilterRecordingContext::EndContent() {
return content;
}
void SVGFilterRecordingContext::Abort() {
if (!paint_controller_)
return;
EndContent();
}
static void PaintFilteredContent(GraphicsContext& context,
const LayoutObject& object,
const DisplayItemClient& display_item_client,
......@@ -78,18 +72,14 @@ static void PaintFilteredContent(GraphicsContext& context,
context.Restore();
}
GraphicsContext* SVGFilterPainter::PrepareEffect(
const LayoutObject& object,
SVGFilterRecordingContext& recording_context) {
filter_.ClearInvalidationMask();
FilterData* SVGFilterPainter::PrepareEffect(const LayoutObject& object) {
SVGElementResourceClient* client = SVGResources::GetClient(object);
if (FilterData* filter_data = client->GetFilterData()) {
// If the filterData already exists we do not need to record the content
// to be filtered. This can occur if the content was previously recorded
// or we are in a cycle.
filter_data->UpdateStateOnPrepare();
return nullptr;
return filter_data;
}
auto* node_map = MakeGarbageCollected<SVGFilterGraphNodeMap>();
......@@ -106,24 +96,15 @@ GraphicsContext* SVGFilterPainter::PrepareEffect(
MakeGarbageCollected<FilterData>(filter->LastEffect(), node_map);
// TODO(pdr): Can this be moved out of painter?
client->SetFilterData(filter_data);
return recording_context.BeginContent();
return filter_data;
}
void SVGFilterPainter::FinishEffect(
const LayoutObject& object,
const DisplayItemClient& display_item_client,
SVGFilterRecordingContext& recording_context) {
SVGElementResourceClient* client = SVGResources::GetClient(object);
FilterData* filter_data = client->GetFilterData();
if (!filter_data) {
// Our state was torn down while we were being painted (selection style for
// <text> can have this effect), or it was never created (invalid filter.)
// In the former case we may have been in the process of recording content,
// so make sure we put recording state into a consistent state.
recording_context.Abort();
return;
}
FilterData* filter_data = SVGResources::GetClient(object)->GetFilterData();
DCHECK(filter_data);
if (!filter_data->UpdateStateOnFinish())
return;
......
......@@ -14,6 +14,7 @@
namespace blink {
class DisplayItemClient;
class FilterData;
class LayoutObject;
class LayoutSVGResourceFilter;
......@@ -26,7 +27,6 @@ class SVGFilterRecordingContext {
GraphicsContext* BeginContent();
sk_sp<PaintRecord> EndContent();
void Abort();
GraphicsContext& PaintingContext() const { return initial_context_; }
......@@ -43,10 +43,9 @@ class SVGFilterPainter {
public:
SVGFilterPainter(LayoutSVGResourceFilter& filter) : filter_(filter) {}
// Returns the context that should be used to paint the filter contents, or
// null if the content should not be recorded.
GraphicsContext* PrepareEffect(const LayoutObject&,
SVGFilterRecordingContext&);
// Returns the FilterData for the filter effect, or null if the
// filter is invalid.
FilterData* PrepareEffect(const LayoutObject&);
void FinishEffect(const LayoutObject&,
const DisplayItemClient&,
SVGFilterRecordingContext&);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment