Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1297)

Unified Diff: cc/output/gl_renderer.cc

Issue 614153002: Refactoring the GLRenderer::GetBackgroundWithFilters method. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « cc/output/gl_renderer.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/output/gl_renderer.cc
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index 6357793c0e2308e24d3032daf4f96ab4e5b1e878..b2d5153767d252f3e2e7b1acd62f05be03eb7ea7 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -850,85 +850,109 @@ static skia::RefPtr<SkImage> ApplyBlendModeWithBackdrop(
return image;
}
-scoped_ptr<ScopedResource> GLRenderer::GetBackgroundWithFilters(
- DrawingFrame* frame,
- const RenderPassDrawQuad* quad,
- const gfx::Transform& contents_device_transform,
- const gfx::Transform& contents_device_transform_inverse,
- bool* background_changed) {
- // This method draws a background filter, which applies a filter to any pixels
- // behind the quad and seen through its background. The algorithm works as
- // follows:
- // 1. Compute a bounding box around the pixels that will be visible through
- // the quad.
- // 2. Read the pixels in the bounding box into a buffer R.
- // 3. Apply the background filter to R, so that it is applied in the pixels'
- // coordinate space.
- // 4. Apply the quad's inverse transform to map the pixels in R into the
- // quad's content space. This implicitly clips R by the content bounds of the
- // quad since the destination texture has bounds matching the quad's content.
- // 5. Draw the background texture for the contents using the same transform as
- // used to draw the contents itself. This is done without blending to replace
- // the current background pixels with the new filtered background.
- // 6. Draw the contents of the quad over drop of the new background with
- // blending, as per usual. The filtered background pixels will show through
- // any non-opaque pixels in this draws.
- //
- // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5.
-
- // TODO(danakj): When this algorithm changes, update
- // LayerTreeHost::PrioritizeTextures() accordingly.
+bool GLRenderer::ShouldApplyBackgroundFilters(DrawingFrame* frame,
+ const RenderPassDrawQuad* quad) {
+ if (quad->background_filters.IsEmpty())
+ return false;
// TODO(danakj): We only allow background filters on an opaque render surface
// because other surfaces may contain translucent pixels, and the contents
// behind those translucent pixels wouldn't have the filter applied.
- bool apply_background_filters =
- !frame->current_render_pass->has_transparent_background;
- DCHECK(!frame->current_texture);
+ if (frame->current_render_pass->has_transparent_background)
+ return false;
// TODO(ajuma): Add support for reference filters once
// FilterOperations::GetOutsets supports reference filters.
- if (apply_background_filters && quad->background_filters.HasReferenceFilter())
- apply_background_filters = false;
+ if (quad->background_filters.HasReferenceFilter())
+ return false;
+ return true;
+}
- // TODO(danakj): Do a single readback for both the surface and replica and
- // cache the filtered results (once filter textures are not reused).
- gfx::Rect window_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect(
+gfx::Rect GLRenderer::GetBackdropBoundingBoxForRenderPassQuad(
+ DrawingFrame* frame,
+ const RenderPassDrawQuad* quad,
+ const gfx::Transform& contents_device_transform) {
+ gfx::Rect backdrop_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect(
contents_device_transform, SharedGeometryQuad().BoundingBox()));
- int top, right, bottom, left;
- quad->background_filters.GetOutsets(&top, &right, &bottom, &left);
- window_rect.Inset(-left, -top, -right, -bottom);
+ if (ShouldApplyBackgroundFilters(frame, quad)) {
+ int top, right, bottom, left;
+ quad->background_filters.GetOutsets(&top, &right, &bottom, &left);
+ backdrop_rect.Inset(-left, -top, -right, -bottom);
+ }
- window_rect.Intersect(
+ backdrop_rect.Intersect(
MoveFromDrawToWindowSpace(frame->current_render_pass->output_rect));
+ return backdrop_rect;
+}
+scoped_ptr<ScopedResource> GLRenderer::GetBackdropTexture(
+ const gfx::Rect& bounding_rect) {
scoped_ptr<ScopedResource> device_background_texture =
ScopedResource::Create(resource_provider_);
// CopyTexImage2D fails when called on a texture having immutable storage.
device_background_texture->Allocate(
- window_rect.size(), ResourceProvider::TextureHintDefault, RGBA_8888);
+ bounding_rect.size(), ResourceProvider::TextureHintDefault, RGBA_8888);
{
ResourceProvider::ScopedWriteLockGL lock(resource_provider_,
device_background_texture->id());
GetFramebufferTexture(
- lock.texture_id(), device_background_texture->format(), window_rect);
+ lock.texture_id(), device_background_texture->format(), bounding_rect);
}
+ return device_background_texture.Pass();
+}
+skia::RefPtr<SkImage> GLRenderer::ApplyBackgroundFilters(
+ DrawingFrame* frame,
+ const RenderPassDrawQuad* quad,
+ ScopedResource* background_texture) {
+ DCHECK(ShouldApplyBackgroundFilters(frame, quad));
skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter(
- quad->background_filters, device_background_texture->size());
+ quad->background_filters, background_texture->size());
- skia::RefPtr<SkImage> filtered_device_background;
- if (apply_background_filters) {
- filtered_device_background =
- ApplyImageFilter(ScopedUseGrContext::Create(this, frame),
- resource_provider_,
- quad->rect.origin(),
- quad->filters_scale,
- filter.get(),
- device_background_texture.get());
- }
- *background_changed = (filtered_device_background != NULL);
+ skia::RefPtr<SkImage> background_with_filters =
+ ApplyImageFilter(ScopedUseGrContext::Create(this, frame),
+ resource_provider_,
+ quad->rect.origin(),
+ quad->filters_scale,
+ filter.get(),
+ background_texture);
+ return background_with_filters;
+}
+
+scoped_ptr<ScopedResource>
+GLRenderer::ApplyInverseTransformForBackgroundFilters(
+ DrawingFrame* frame,
+ const RenderPassDrawQuad* quad,
+ const gfx::Transform& contents_device_transform_inverse,
+ ScopedResource* device_background_texture,
+ skia::RefPtr<SkImage> filtered_device_background,
+ const gfx::Rect& backdrop_bounding_rect) {
+ // This method draws a background filter, which applies a filter to any pixels
+ // behind the quad and seen through its background. The algorithm works as
+ // follows:
+ // 1. Read the pixels in the bounding box into a buffer.
+ // Moved to GLRenderer::GetBackdropBoundingBoxForRenderPassQuad().
+ // 2. Read the pixels in the bounding box into a buffer R.
+ // Moved to GLRenderer::GetBackdropTexture().
+ // 3. Apply the background filter to R, so that it is applied in the pixels'
+ // coordinate space. Moved to GLRenderer::ApplyBackgroundFilters().
+ // 4. Apply the quad's inverse transform to map the pixels in R into the
+ // quad's content space. This implicitly clips R by the content bounds of the
+ // quad since the destination texture has bounds matching the quad's content.
+ // 5. Draw the background texture for the contents using the same transform as
+ // used to draw the contents itself. This is done without blending to replace
+ // the current background pixels with the new filtered background.
+ // 6. Draw the contents of the quad over drop of the new background with
+ // blending, as per usual. The filtered background pixels will show through
+ // any non-opaque pixels in this draws.
+ //
+ // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5.
+
+ // TODO(danakj): When this algorithm changes, update
+ // LayerTreeHost::PrioritizeTextures() accordingly.
+
+ DCHECK(device_background_texture);
int filtered_device_background_texture_id = 0;
scoped_ptr<ResourceProvider::ScopedReadLockGL> lock;
@@ -966,15 +990,15 @@ scoped_ptr<ScopedResource> GLRenderer::GetBackgroundWithFilters(
gl_->Clear(GL_COLOR_BUFFER_BIT);
#endif
- // The filtered_deveice_background_texture is oriented the same as the frame
- // buffer. The transform we are copying with has a vertical flip, as well as
+ // The background_texture is oriented the same as the frame buffer.
+ // The transform we are copying with has a vertical flip, as well as
// the |device_to_framebuffer_transform|, which cancel each other out. So do
// not flip the contents in the shader to maintain orientation.
bool flip_vertically = false;
CopyTextureToFramebuffer(frame,
filtered_device_background_texture_id,
- window_rect,
+ backdrop_bounding_rect,
device_to_framebuffer_transform,
flip_vertically);
}
@@ -1009,8 +1033,8 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
return;
bool need_background_texture = !ShouldApplyBlendModeUsingBlendFunc(quad) ||
- !quad->background_filters.IsEmpty();
- bool background_changed = false;
+ ShouldApplyBackgroundFilters(frame, quad);
+
scoped_ptr<ScopedResource> background_texture;
if (need_background_texture) {
// The pixels from the filtered background should completely replace the
@@ -1019,12 +1043,33 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
if (disable_blending)
SetBlendEnabled(false);
- background_texture =
- GetBackgroundWithFilters(frame,
- quad,
- contents_device_transform,
- contents_device_transform_inverse,
- &background_changed);
+ // Compute a bounding box around the pixels that will be visible through
+ // the quad.
+ gfx::Rect backdrop_rect = GetBackdropBoundingBoxForRenderPassQuad(
+ frame, quad, contents_device_transform);
+
+ // Read the pixels in the bounding box into a buffer R.
+ scoped_ptr<ScopedResource> scoped_background_texture =
+ GetBackdropTexture(backdrop_rect);
+
+ skia::RefPtr<SkImage> background_with_filters;
+ if (ShouldApplyBackgroundFilters(frame, quad)) {
+ // Apply the background filters to R, so that it is applied in the pixels'
+ // coordinate space.
+ background_with_filters =
+ ApplyBackgroundFilters(frame, quad, scoped_background_texture.get());
+ }
+ // Apply the quad's inverse transform to map the pixels in R into the
+ // quad's content space. This implicitly clips R by the content bounds of
+ // the quad since the destination texture has bounds matching the quad's
+ // content.
+ background_texture = ApplyInverseTransformForBackgroundFilters(
+ frame,
+ quad,
+ contents_device_transform_inverse,
+ scoped_background_texture.get(),
+ background_with_filters,
+ backdrop_rect);
if (disable_blending)
SetBlendEnabled(true);
@@ -1063,6 +1108,9 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
}
}
+ // If blending is applied using shaders, the background texture with
+ // filters will be used as backdrop for blending operation, so we don't
+ // need to copy it to the frame buffer.
if (background_texture && !ShouldApplyBlendModeUsingBlendFunc(quad)) {
filter_bitmap =
ApplyBlendModeWithBackdrop(ScopedUseGrContext::Create(this, frame),
@@ -1071,10 +1119,9 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
contents_texture,
background_texture.get(),
quad->shared_quad_state->blend_mode);
- }
-
- // Draw the background texture if it has some filters applied.
- if (background_texture && background_changed) {
+ } else if (background_texture) {
+ // Draw the background texture if it has some filters applied.
+ DCHECK(ShouldApplyBackgroundFilters(frame, quad));
DCHECK(background_texture->size() == quad->rect.size());
ResourceProvider::ScopedReadLockGL lock(resource_provider_,
background_texture->id());
« no previous file with comments | « cc/output/gl_renderer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698