Commit 25d111bb authored by Mason Freed's avatar Mason Freed Committed by Commit Bot

Clip backdrop_filter input rect to the device viewport

Prior to this CL, the entire parent surface was read back to form the
input for the backdrop-filter. In some cases (e.g. crbug.com/993971),
that parent surface was very large, resulting in very large readbacks,
and poor performance. With this CL, which is a perf optimization, the
readback rect is intersected with the device viewport (expanded for
pixel moving filters) prior to readback. Pixels outside of the
viewport will not contribute to the visible filtered content.

Bug: 993971, 974789
Change-Id: I429c8dcb335b264873b3a3671225d19162ecfe27
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1761346
Auto-Submit: Mason Freed <masonfreed@chromium.org>
Reviewed-by: default avatarenne <enne@chromium.org>
Commit-Queue: enne <enne@chromium.org>
Cr-Commit-Position: refs/heads/master@{#689536}
parent 8390f96c
......@@ -104,6 +104,43 @@ bool FilterOperations::HasFilterThatMovesPixels() const {
return false;
}
float FilterOperations::MaximumPixelMovement() const {
float max_movement = 0.;
for (size_t i = 0; i < operations_.size(); ++i) {
const FilterOperation& op = operations_[i];
switch (op.type()) {
case FilterOperation::BLUR:
max_movement = fmax(max_movement, op.amount() * 2);
continue;
case FilterOperation::DROP_SHADOW:
max_movement = fmax(max_movement, fmax(op.drop_shadow_offset().x(),
op.drop_shadow_offset().y()));
continue;
case FilterOperation::ZOOM:
max_movement = fmax(max_movement, op.zoom_inset());
continue;
case FilterOperation::REFERENCE:
// TODO(hendrikw): SkImageFilter needs a function that tells us how far
// the filter can move pixels. See crbug.com/523538 (sort of).
max_movement = fmax(max_movement, 100);
continue;
case FilterOperation::OPACITY:
case FilterOperation::COLOR_MATRIX:
case FilterOperation::GRAYSCALE:
case FilterOperation::SEPIA:
case FilterOperation::SATURATE:
case FilterOperation::HUE_ROTATE:
case FilterOperation::INVERT:
case FilterOperation::BRIGHTNESS:
case FilterOperation::CONTRAST:
case FilterOperation::SATURATING_BRIGHTNESS:
case FilterOperation::ALPHA_THRESHOLD:
continue;
}
}
return max_movement;
}
bool FilterOperations::HasFilterThatAffectsOpacity() const {
for (size_t i = 0; i < operations_.size(); ++i) {
const FilterOperation& op = operations_[i];
......
......@@ -62,6 +62,7 @@ class CC_PAINT_EXPORT FilterOperations {
gfx::Rect MapRectReverse(const gfx::Rect& rect, const SkMatrix& matrix) const;
bool HasFilterThatMovesPixels() const;
float MaximumPixelMovement() const;
bool HasFilterThatAffectsOpacity() const;
bool HasReferenceFilter() const;
......
......@@ -782,6 +782,12 @@ gfx::Rect GLRenderer::GetBackdropBoundingBoxForRenderPassQuad(
*unclipped_rect = backdrop_rect;
backdrop_rect.Intersect(MoveFromDrawToWindowSpace(
current_frame()->current_render_pass->output_rect));
if (ShouldApplyBackdropFilters(params->backdrop_filters)) {
float max_pixel_movement = params->backdrop_filters->MaximumPixelMovement();
gfx::Rect scissor_rect(current_window_space_viewport_);
scissor_rect.Inset(-max_pixel_movement, -max_pixel_movement);
backdrop_rect.Intersect(scissor_rect);
}
// The frame buffer flip is already included in the captured backdrop image,
// and it is included in |contents_device_transform| (through
......
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