Chromium Code Reviews| Index: cc/output/gl_renderer.cc |
| diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc |
| index 67c8d518cbf4d13f5b8210789fb789c1724eb83f..d8b2e611bb38b0340b3af07123a8ce4813d0a851 100644 |
| --- a/cc/output/gl_renderer.cc |
| +++ b/cc/output/gl_renderer.cc |
| @@ -865,85 +865,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; |
| @@ -981,15 +1005,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); |
| } |
| @@ -1026,8 +1050,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
| return; |
| bool need_background_texture = !CanApplyBlendModeUsingBlendFunc(blend_mode) || |
| - !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 |
| @@ -1036,12 +1059,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 |
|
enne (OOO)
2014/10/07 19:52:55
Missing apostrophe
rosca
2014/10/08 09:32:46
Done.
|
| + // 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); |
| @@ -1080,6 +1124,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 && !CanApplyBlendModeUsingBlendFunc(blend_mode)) { |
|
Erik Dahlström (inactive)
2014/10/06 15:28:35
Why not merge the if-statement here with the one o
rosca
2014/10/08 09:32:46
Done.
|
| filter_bitmap = |
| ApplyBlendModeWithBackdrop(ScopedUseGrContext::Create(this, frame), |
| @@ -1091,7 +1138,8 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
| } |
| // Draw the background texture if it has some filters applied. |
| - if (background_texture && background_changed) { |
| + if (background_texture && CanApplyBlendModeUsingBlendFunc(blend_mode)) { |
| + DCHECK(ShouldApplyBackgroundFilters(frame, quad)); |
| DCHECK(background_texture->size() == quad->rect.size()); |
| ResourceProvider::ScopedReadLockGL lock(resource_provider_, |
| background_texture->id()); |