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

Side by Side Diff: cc/output/gl_renderer.cc

Issue 1517693002: Accelerated filters should filter unpadded primitives. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Expand the RenderSurface's drawable_content_rect for filter outsets. Created 4 years, 11 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 unified diff | Download patch
OLDNEW
1 // Copyright 2010 The Chromium Authors. All rights reserved. 1 // Copyright 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/output/gl_renderer.h" 5 #include "cc/output/gl_renderer.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 #include "third_party/skia/include/core/SkColor.h" 49 #include "third_party/skia/include/core/SkColor.h"
50 #include "third_party/skia/include/core/SkColorFilter.h" 50 #include "third_party/skia/include/core/SkColorFilter.h"
51 #include "third_party/skia/include/core/SkImage.h" 51 #include "third_party/skia/include/core/SkImage.h"
52 #include "third_party/skia/include/core/SkSurface.h" 52 #include "third_party/skia/include/core/SkSurface.h"
53 #include "third_party/skia/include/gpu/GrContext.h" 53 #include "third_party/skia/include/gpu/GrContext.h"
54 #include "third_party/skia/include/gpu/GrTexture.h" 54 #include "third_party/skia/include/gpu/GrTexture.h"
55 #include "third_party/skia/include/gpu/GrTextureProvider.h" 55 #include "third_party/skia/include/gpu/GrTextureProvider.h"
56 #include "third_party/skia/include/gpu/gl/GrGLInterface.h" 56 #include "third_party/skia/include/gpu/gl/GrGLInterface.h"
57 #include "ui/gfx/geometry/quad_f.h" 57 #include "ui/gfx/geometry/quad_f.h"
58 #include "ui/gfx/geometry/rect_conversions.h" 58 #include "ui/gfx/geometry/rect_conversions.h"
59 #include "ui/gfx/skia_util.h"
59 60
60 using gpu::gles2::GLES2Interface; 61 using gpu::gles2::GLES2Interface;
61 62
62 namespace cc { 63 namespace cc {
63 namespace { 64 namespace {
64 65
65 bool NeedsIOSurfaceReadbackWorkaround() { 66 bool NeedsIOSurfaceReadbackWorkaround() {
66 #if defined(OS_MACOSX) 67 #if defined(OS_MACOSX)
67 // This isn't strictly required in DumpRenderTree-mode when Mesa is used, 68 // This isn't strictly required in DumpRenderTree-mode when Mesa is used,
68 // but it doesn't seem to hurt. 69 // but it doesn't seem to hurt.
(...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 gl_->LineWidth(quad->width); 595 gl_->LineWidth(quad->width);
595 596
596 // The indices for the line are stored in the same array as the triangle 597 // The indices for the line are stored in the same array as the triangle
597 // indices. 598 // indices.
598 gl_->DrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, 0); 599 gl_->DrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, 0);
599 } 600 }
600 601
601 static skia::RefPtr<SkImage> ApplyImageFilter( 602 static skia::RefPtr<SkImage> ApplyImageFilter(
602 scoped_ptr<GLRenderer::ScopedUseGrContext> use_gr_context, 603 scoped_ptr<GLRenderer::ScopedUseGrContext> use_gr_context,
603 ResourceProvider* resource_provider, 604 ResourceProvider* resource_provider,
604 const gfx::Rect& rect, 605 const gfx::RectF& src_rect,
606 const gfx::RectF& dst_rect,
605 const gfx::Vector2dF& scale, 607 const gfx::Vector2dF& scale,
606 SkImageFilter* filter, 608 SkImageFilter* filter,
607 ScopedResource* source_texture_resource) { 609 ScopedResource* source_texture_resource) {
608 if (!filter) 610 if (!filter)
609 return skia::RefPtr<SkImage>(); 611 return skia::RefPtr<SkImage>();
610 612
611 if (!use_gr_context) 613 if (!use_gr_context)
612 return skia::RefPtr<SkImage>(); 614 return skia::RefPtr<SkImage>();
613 615
614 ResourceProvider::ScopedReadLockGL lock(resource_provider, 616 ResourceProvider::ScopedReadLockGL lock(resource_provider,
(...skipping 12 matching lines...) Expand all
627 use_gr_context->context(), backend_texture_description)); 629 use_gr_context->context(), backend_texture_description));
628 if (!srcImage.get()) { 630 if (!srcImage.get()) {
629 TRACE_EVENT_INSTANT0("cc", 631 TRACE_EVENT_INSTANT0("cc",
630 "ApplyImageFilter wrap background texture failed", 632 "ApplyImageFilter wrap background texture failed",
631 TRACE_EVENT_SCOPE_THREAD); 633 TRACE_EVENT_SCOPE_THREAD);
632 return skia::RefPtr<SkImage>(); 634 return skia::RefPtr<SkImage>();
633 } 635 }
634 636
635 // Create surface to draw into. 637 // Create surface to draw into.
636 SkImageInfo dst_info = 638 SkImageInfo dst_info =
637 SkImageInfo::MakeN32Premul(srcImage->width(), srcImage->height()); 639 SkImageInfo::MakeN32Premul(dst_rect.width(), dst_rect.height());
638 skia::RefPtr<SkSurface> surface = skia::AdoptRef(SkSurface::NewRenderTarget( 640 skia::RefPtr<SkSurface> surface = skia::AdoptRef(SkSurface::NewRenderTarget(
639 use_gr_context->context(), SkSurface::kYes_Budgeted, dst_info, 0)); 641 use_gr_context->context(), SkSurface::kYes_Budgeted, dst_info, 0));
640 if (!surface) { 642 if (!surface) {
641 TRACE_EVENT_INSTANT0("cc", "ApplyImageFilter surface allocation failed", 643 TRACE_EVENT_INSTANT0("cc", "ApplyImageFilter surface allocation failed",
642 TRACE_EVENT_SCOPE_THREAD); 644 TRACE_EVENT_SCOPE_THREAD);
643 return skia::RefPtr<SkImage>(); 645 return skia::RefPtr<SkImage>();
644 } 646 }
645 647
646 // The origin of the filter is top-left and the origin of the source is 648 // The origin of the filter is top-left and the origin of the source is
647 // bottom-left, but the orientation is the same, so we must translate the 649 // bottom-left, but the orientation is the same, so we must translate the
648 // filter so that it renders at the bottom of the texture to avoid 650 // filter so that it renders at the bottom of the texture to avoid
649 // misregistration. 651 // misregistration.
650 int y_translate = source_texture_resource->size().height() - rect.height() - 652 float y_offset = source_texture_resource->size().height() - src_rect.height();
651 rect.origin().y();
652 SkMatrix localM; 653 SkMatrix localM;
enne (OOO) 2016/01/19 23:21:19 localM and localIMF are not chrome style. Could y
Stephen White 2016/01/19 23:59:10 Done.
653 localM.setTranslate(-rect.origin().x(), y_translate); 654 localM.setScale(scale.x(), scale.y());
654 localM.preScale(scale.x(), scale.y());
655 skia::RefPtr<SkImageFilter> localIMF = 655 skia::RefPtr<SkImageFilter> localIMF =
656 skia::AdoptRef(filter->newWithLocalMatrix(localM)); 656 skia::AdoptRef(filter->newWithLocalMatrix(localM));
657 657
658 SkPaint paint; 658 SkPaint paint;
659 paint.setImageFilter(localIMF.get()); 659 paint.setImageFilter(localIMF.get());
660 surface->getCanvas()->drawImage(srcImage.get(), 0, 0, &paint); 660 surface->getCanvas()->translate(-dst_rect.x(), -dst_rect.y());
661 surface->getCanvas()->drawImage(srcImage.get(), src_rect.x(),
662 src_rect.y() - y_offset, &paint);
661 663
662 skia::RefPtr<SkImage> image = skia::AdoptRef(surface->newImageSnapshot()); 664 skia::RefPtr<SkImage> image = skia::AdoptRef(surface->newImageSnapshot());
663 if (!image || !image->isTextureBacked()) { 665 if (!image || !image->isTextureBacked()) {
664 return skia::RefPtr<SkImage>(); 666 return skia::RefPtr<SkImage>();
665 } 667 }
666 668
667 CHECK(image->isTextureBacked()); 669 CHECK(image->isTextureBacked());
668 return image; 670 return image;
669 } 671 }
670 672
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
839 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, 841 ResourceProvider::ScopedWriteLockGL lock(resource_provider_,
840 device_background_texture->id()); 842 device_background_texture->id());
841 GetFramebufferTexture(lock.texture_id(), RGBA_8888, bounding_rect); 843 GetFramebufferTexture(lock.texture_id(), RGBA_8888, bounding_rect);
842 } 844 }
843 return device_background_texture; 845 return device_background_texture;
844 } 846 }
845 847
846 skia::RefPtr<SkImage> GLRenderer::ApplyBackgroundFilters( 848 skia::RefPtr<SkImage> GLRenderer::ApplyBackgroundFilters(
847 DrawingFrame* frame, 849 DrawingFrame* frame,
848 const RenderPassDrawQuad* quad, 850 const RenderPassDrawQuad* quad,
849 ScopedResource* background_texture) { 851 ScopedResource* background_texture,
852 const gfx::RectF& rect) {
850 DCHECK(ShouldApplyBackgroundFilters(quad)); 853 DCHECK(ShouldApplyBackgroundFilters(quad));
851 skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter( 854 skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter(
852 quad->background_filters, gfx::SizeF(background_texture->size())); 855 quad->background_filters, gfx::SizeF(background_texture->size()));
853 856
854 skia::RefPtr<SkImage> background_with_filters = ApplyImageFilter( 857 skia::RefPtr<SkImage> background_with_filters = ApplyImageFilter(
855 ScopedUseGrContext::Create(this, frame), resource_provider_, quad->rect, 858 ScopedUseGrContext::Create(this, frame), resource_provider_, rect, rect,
856 quad->filters_scale, filter.get(), background_texture); 859 quad->filters_scale, filter.get(), background_texture);
857 return background_with_filters; 860 return background_with_filters;
858 } 861 }
859 862
860 void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, 863 void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
861 const RenderPassDrawQuad* quad, 864 const RenderPassDrawQuad* quad,
862 const gfx::QuadF* clip_region) { 865 const gfx::QuadF* clip_region) {
863 ScopedResource* contents_texture = 866 ScopedResource* contents_texture =
864 render_pass_textures_.get(quad->render_pass_id); 867 render_pass_textures_.get(quad->render_pass_id);
865 DCHECK(contents_texture); 868 DCHECK(contents_texture);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
918 921
919 // Read the pixels in the bounding box into a buffer R. 922 // Read the pixels in the bounding box into a buffer R.
920 // This function allocates a texture, which should contribute to the 923 // This function allocates a texture, which should contribute to the
921 // amount of memory used by render surfaces: 924 // amount of memory used by render surfaces:
922 // LayerTreeHost::CalculateMemoryForRenderSurfaces. 925 // LayerTreeHost::CalculateMemoryForRenderSurfaces.
923 background_texture = GetBackdropTexture(background_rect); 926 background_texture = GetBackdropTexture(background_rect);
924 927
925 if (ShouldApplyBackgroundFilters(quad) && background_texture) { 928 if (ShouldApplyBackgroundFilters(quad) && background_texture) {
926 // Apply the background filters to R, so that it is applied in the 929 // Apply the background filters to R, so that it is applied in the
927 // pixels' coordinate space. 930 // pixels' coordinate space.
928 background_image = 931 background_image = ApplyBackgroundFilters(
929 ApplyBackgroundFilters(frame, quad, background_texture.get()); 932 frame, quad, background_texture.get(), gfx::RectF(background_rect));
930 if (background_image) 933 if (background_image)
931 background_image_id = background_image->getTextureHandle(true); 934 background_image_id = background_image->getTextureHandle(true);
932 DCHECK(background_image_id); 935 DCHECK(background_image_id);
933 } 936 }
934 } 937 }
935 938
936 if (!background_texture) { 939 if (!background_texture) {
937 // Something went wrong with reading the backdrop. 940 // Something went wrong with reading the backdrop.
938 DCHECK(!background_image_id); 941 DCHECK(!background_image_id);
939 use_shaders_for_blending = false; 942 use_shaders_for_blending = false;
(...skipping 16 matching lines...) Expand all
956 SetBlendEnabled( 959 SetBlendEnabled(
957 !use_shaders_for_blending && 960 !use_shaders_for_blending &&
958 (quad->ShouldDrawWithBlending() || !IsDefaultBlendMode(blend_mode))); 961 (quad->ShouldDrawWithBlending() || !IsDefaultBlendMode(blend_mode)));
959 962
960 // TODO(senorblanco): Cache this value so that we don't have to do it for both 963 // TODO(senorblanco): Cache this value so that we don't have to do it for both
961 // the surface and its replica. Apply filters to the contents texture. 964 // the surface and its replica. Apply filters to the contents texture.
962 skia::RefPtr<SkImage> filter_image; 965 skia::RefPtr<SkImage> filter_image;
963 GLuint filter_image_id = 0; 966 GLuint filter_image_id = 0;
964 SkScalar color_matrix[20]; 967 SkScalar color_matrix[20];
965 bool use_color_matrix = false; 968 bool use_color_matrix = false;
969 gfx::RectF rect = gfx::RectF(quad->rect);
966 if (!quad->filters.IsEmpty()) { 970 if (!quad->filters.IsEmpty()) {
967 skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter( 971 skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter(
968 quad->filters, gfx::SizeF(contents_texture->size())); 972 quad->filters, gfx::SizeF(contents_texture->size()));
969 if (filter) { 973 if (filter) {
970 skia::RefPtr<SkColorFilter> cf; 974 skia::RefPtr<SkColorFilter> cf;
971 975
972 { 976 {
973 SkColorFilter* colorfilter_rawptr = NULL; 977 SkColorFilter* colorfilter_rawptr = NULL;
974 filter->asColorFilter(&colorfilter_rawptr); 978 filter->asColorFilter(&colorfilter_rawptr);
975 cf = skia::AdoptRef(colorfilter_rawptr); 979 cf = skia::AdoptRef(colorfilter_rawptr);
976 } 980 }
977 981
978 if (cf && cf->asColorMatrix(color_matrix) && !filter->getInput(0)) { 982 if (cf && cf->asColorMatrix(color_matrix) && !filter->getInput(0)) {
979 // We have a single color matrix as a filter; apply it locally 983 // We have a single color matrix as a filter; apply it locally
980 // in the compositor. 984 // in the compositor.
981 use_color_matrix = true; 985 use_color_matrix = true;
982 } else { 986 } else {
983 filter_image = ApplyImageFilter( 987 gfx::RectF src_rect = rect;
984 ScopedUseGrContext::Create(this, frame), resource_provider_, 988 gfx::Vector2dF scale = quad->filters_scale;
985 quad->rect, quad->filters_scale, filter.get(), contents_texture); 989 if (filter->canComputeFastBounds()) {
enne (OOO) 2016/01/19 23:21:19 What if it can't? Does it just not expand at all?
Stephen White 2016/01/19 23:59:10 That's actually current behaviour (even though it'
990 SkRect result_rect;
991 rect.Scale(1.0f / scale.x(), 1.0f / scale.y());
992 filter->computeFastBounds(gfx::RectFToSkRect(rect), &result_rect);
993 rect = gfx::SkRectToRectF(result_rect);
994 rect.Scale(scale.x(), scale.y());
995 }
996 filter_image = ApplyImageFilter(ScopedUseGrContext::Create(this, frame),
997 resource_provider_, src_rect, rect,
998 scale, filter.get(), contents_texture);
986 if (filter_image) { 999 if (filter_image) {
987 filter_image_id = filter_image->getTextureHandle(true); 1000 filter_image_id = filter_image->getTextureHandle(true);
988 DCHECK(filter_image_id); 1001 DCHECK(filter_image_id);
989 } 1002 }
990 } 1003 }
991 } 1004 }
992 } 1005 }
993 1006
994 scoped_ptr<ResourceProvider::ScopedSamplerGL> mask_resource_lock; 1007 scoped_ptr<ResourceProvider::ScopedSamplerGL> mask_resource_lock;
995 unsigned mask_texture_id = 0; 1008 unsigned mask_texture_id = 0;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1089 program->fragment_shader().FillLocations(&locations); 1102 program->fragment_shader().FillLocations(&locations);
1090 gl_->Uniform1i(locations.sampler, 0); 1103 gl_->Uniform1i(locations.sampler, 0);
1091 } else { 1104 } else {
1092 const RenderPassProgram* program = 1105 const RenderPassProgram* program =
1093 GetRenderPassProgram(tex_coord_precision, shader_blend_mode); 1106 GetRenderPassProgram(tex_coord_precision, shader_blend_mode);
1094 SetUseProgram(program->program()); 1107 SetUseProgram(program->program());
1095 program->vertex_shader().FillLocations(&locations); 1108 program->vertex_shader().FillLocations(&locations);
1096 program->fragment_shader().FillLocations(&locations); 1109 program->fragment_shader().FillLocations(&locations);
1097 gl_->Uniform1i(locations.sampler, 0); 1110 gl_->Uniform1i(locations.sampler, 0);
1098 } 1111 }
1099 float tex_scale_x = 1112 float tex_scale_x, tex_scale_y;
1100 quad->rect.width() / static_cast<float>(contents_texture->size().width()); 1113 if (filter_image) {
1101 float tex_scale_y = quad->rect.height() / 1114 // Skia filters always return SkImages with snug textures.
1102 static_cast<float>(contents_texture->size().height()); 1115 tex_scale_x = tex_scale_y = 1.0f;
1116 } else {
1117 tex_scale_x = quad->rect.width() /
1118 static_cast<float>(contents_texture->size().width());
1119 tex_scale_y = quad->rect.height() /
1120 static_cast<float>(contents_texture->size().height());
1121 }
1103 DCHECK_LE(tex_scale_x, 1.0f); 1122 DCHECK_LE(tex_scale_x, 1.0f);
1104 DCHECK_LE(tex_scale_y, 1.0f); 1123 DCHECK_LE(tex_scale_y, 1.0f);
1105 1124
1106 DCHECK(locations.tex_transform != -1 || IsContextLost()); 1125 DCHECK(locations.tex_transform != -1 || IsContextLost());
1107 // Flip the content vertically in the shader, as the RenderPass input 1126 // Flip the content vertically in the shader, as the RenderPass input
1108 // texture is already oriented the same way as the framebuffer, but the 1127 // texture is already oriented the same way as the framebuffer, but the
1109 // projection transform does a flip. 1128 // projection transform does a flip.
1110 gl_->Uniform4f(locations.tex_transform, 0.0f, tex_scale_y, tex_scale_x, 1129 gl_->Uniform4f(locations.tex_transform, 0.0f, tex_scale_y, tex_scale_x,
1111 -tex_scale_y); 1130 -tex_scale_y);
1112 1131
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1190 GL_TEXTURE0 + last_texture_unit, 1209 GL_TEXTURE0 + last_texture_unit,
1191 GL_LINEAR)); 1210 GL_LINEAR));
1192 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), 1211 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
1193 shader_background_sampler_lock->target()); 1212 shader_background_sampler_lock->target());
1194 } 1213 }
1195 } 1214 }
1196 1215
1197 SetShaderOpacity(quad->shared_quad_state->opacity, locations.alpha); 1216 SetShaderOpacity(quad->shared_quad_state->opacity, locations.alpha);
1198 SetShaderQuadF(surface_quad, locations.quad); 1217 SetShaderQuadF(surface_quad, locations.quad);
1199 DrawQuadGeometry(frame, quad->shared_quad_state->quad_to_target_transform, 1218 DrawQuadGeometry(frame, quad->shared_quad_state->quad_to_target_transform,
1200 gfx::RectF(quad->rect), locations.matrix); 1219 rect, locations.matrix);
1201 1220
1202 // Flush the compositor context before the filter bitmap goes out of 1221 // Flush the compositor context before the filter bitmap goes out of
1203 // scope, so the draw gets processed before the filter texture gets deleted. 1222 // scope, so the draw gets processed before the filter texture gets deleted.
1204 if (filter_image_id) 1223 if (filter_image_id)
1205 gl_->Flush(); 1224 gl_->Flush();
1206 1225
1207 if (!use_shaders_for_blending) 1226 if (!use_shaders_for_blending)
1208 RestoreBlendFuncToDefault(blend_mode); 1227 RestoreBlendFuncToDefault(blend_mode);
1209 } 1228 }
1210 1229
(...skipping 2374 matching lines...) Expand 10 before | Expand all | Expand 10 after
3585 texture_id = pending_overlay_resources_.back()->texture_id(); 3604 texture_id = pending_overlay_resources_.back()->texture_id();
3586 } 3605 }
3587 3606
3588 context_support_->ScheduleOverlayPlane( 3607 context_support_->ScheduleOverlayPlane(
3589 overlay.plane_z_order, overlay.transform, texture_id, 3608 overlay.plane_z_order, overlay.transform, texture_id,
3590 ToNearestRect(overlay.display_rect), overlay.uv_rect); 3609 ToNearestRect(overlay.display_rect), overlay.uv_rect);
3591 } 3610 }
3592 } 3611 }
3593 3612
3594 } // namespace cc 3613 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698