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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « cc/output/gl_renderer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 #include <set> 9 #include <set>
10 #include <string> 10 #include <string>
(...skipping 832 matching lines...) Expand 10 before | Expand all | Expand 10 after
843 } 843 }
844 844
845 // Flush the GrContext to ensure all buffered GL calls are drawn to the 845 // Flush the GrContext to ensure all buffered GL calls are drawn to the
846 // backing store before we access and return it, and have cc begin using the 846 // backing store before we access and return it, and have cc begin using the
847 // GL context again. 847 // GL context again.
848 canvas->flush(); 848 canvas->flush();
849 849
850 return image; 850 return image;
851 } 851 }
852 852
853 scoped_ptr<ScopedResource> GLRenderer::GetBackgroundWithFilters( 853 bool GLRenderer::ShouldApplyBackgroundFilters(DrawingFrame* frame,
854 const RenderPassDrawQuad* quad) {
855 if (quad->background_filters.IsEmpty())
856 return false;
857
858 // TODO(danakj): We only allow background filters on an opaque render surface
859 // because other surfaces may contain translucent pixels, and the contents
860 // behind those translucent pixels wouldn't have the filter applied.
861 if (frame->current_render_pass->has_transparent_background)
862 return false;
863
864 // TODO(ajuma): Add support for reference filters once
865 // FilterOperations::GetOutsets supports reference filters.
866 if (quad->background_filters.HasReferenceFilter())
867 return false;
868 return true;
869 }
870
871 gfx::Rect GLRenderer::GetBackdropBoundingBoxForRenderPassQuad(
854 DrawingFrame* frame, 872 DrawingFrame* frame,
855 const RenderPassDrawQuad* quad, 873 const RenderPassDrawQuad* quad,
856 const gfx::Transform& contents_device_transform, 874 const gfx::Transform& contents_device_transform) {
875 gfx::Rect backdrop_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect(
876 contents_device_transform, SharedGeometryQuad().BoundingBox()));
877
878 if (ShouldApplyBackgroundFilters(frame, quad)) {
879 int top, right, bottom, left;
880 quad->background_filters.GetOutsets(&top, &right, &bottom, &left);
881 backdrop_rect.Inset(-left, -top, -right, -bottom);
882 }
883
884 backdrop_rect.Intersect(
885 MoveFromDrawToWindowSpace(frame->current_render_pass->output_rect));
886 return backdrop_rect;
887 }
888
889 scoped_ptr<ScopedResource> GLRenderer::GetBackdropTexture(
890 const gfx::Rect& bounding_rect) {
891 scoped_ptr<ScopedResource> device_background_texture =
892 ScopedResource::Create(resource_provider_);
893 // CopyTexImage2D fails when called on a texture having immutable storage.
894 device_background_texture->Allocate(
895 bounding_rect.size(), ResourceProvider::TextureHintDefault, RGBA_8888);
896 {
897 ResourceProvider::ScopedWriteLockGL lock(resource_provider_,
898 device_background_texture->id());
899 GetFramebufferTexture(
900 lock.texture_id(), device_background_texture->format(), bounding_rect);
901 }
902 return device_background_texture.Pass();
903 }
904
905 skia::RefPtr<SkImage> GLRenderer::ApplyBackgroundFilters(
906 DrawingFrame* frame,
907 const RenderPassDrawQuad* quad,
908 ScopedResource* background_texture) {
909 DCHECK(ShouldApplyBackgroundFilters(frame, quad));
910 skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter(
911 quad->background_filters, background_texture->size());
912
913 skia::RefPtr<SkImage> background_with_filters =
914 ApplyImageFilter(ScopedUseGrContext::Create(this, frame),
915 resource_provider_,
916 quad->rect.origin(),
917 quad->filters_scale,
918 filter.get(),
919 background_texture);
920 return background_with_filters;
921 }
922
923 scoped_ptr<ScopedResource>
924 GLRenderer::ApplyInverseTransformForBackgroundFilters(
925 DrawingFrame* frame,
926 const RenderPassDrawQuad* quad,
857 const gfx::Transform& contents_device_transform_inverse, 927 const gfx::Transform& contents_device_transform_inverse,
858 bool* background_changed) { 928 ScopedResource* device_background_texture,
929 skia::RefPtr<SkImage> filtered_device_background,
930 const gfx::Rect& backdrop_bounding_rect) {
859 // This method draws a background filter, which applies a filter to any pixels 931 // This method draws a background filter, which applies a filter to any pixels
860 // behind the quad and seen through its background. The algorithm works as 932 // behind the quad and seen through its background. The algorithm works as
861 // follows: 933 // follows:
862 // 1. Compute a bounding box around the pixels that will be visible through 934 // 1. Read the pixels in the bounding box into a buffer.
863 // the quad. 935 // Moved to GLRenderer::GetBackdropBoundingBoxForRenderPassQuad().
864 // 2. Read the pixels in the bounding box into a buffer R. 936 // 2. Read the pixels in the bounding box into a buffer R.
937 // Moved to GLRenderer::GetBackdropTexture().
865 // 3. Apply the background filter to R, so that it is applied in the pixels' 938 // 3. Apply the background filter to R, so that it is applied in the pixels'
866 // coordinate space. 939 // coordinate space. Moved to GLRenderer::ApplyBackgroundFilters().
867 // 4. Apply the quad's inverse transform to map the pixels in R into the 940 // 4. Apply the quad's inverse transform to map the pixels in R into the
868 // quad's content space. This implicitly clips R by the content bounds of the 941 // quad's content space. This implicitly clips R by the content bounds of the
869 // quad since the destination texture has bounds matching the quad's content. 942 // quad since the destination texture has bounds matching the quad's content.
870 // 5. Draw the background texture for the contents using the same transform as 943 // 5. Draw the background texture for the contents using the same transform as
871 // used to draw the contents itself. This is done without blending to replace 944 // used to draw the contents itself. This is done without blending to replace
872 // the current background pixels with the new filtered background. 945 // the current background pixels with the new filtered background.
873 // 6. Draw the contents of the quad over drop of the new background with 946 // 6. Draw the contents of the quad over drop of the new background with
874 // blending, as per usual. The filtered background pixels will show through 947 // blending, as per usual. The filtered background pixels will show through
875 // any non-opaque pixels in this draws. 948 // any non-opaque pixels in this draws.
876 // 949 //
877 // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5. 950 // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5.
878 951
879 // TODO(danakj): When this algorithm changes, update 952 // TODO(danakj): When this algorithm changes, update
880 // LayerTreeHost::PrioritizeTextures() accordingly. 953 // LayerTreeHost::PrioritizeTextures() accordingly.
881 954
882 // TODO(danakj): We only allow background filters on an opaque render surface 955 DCHECK(device_background_texture);
883 // because other surfaces may contain translucent pixels, and the contents
884 // behind those translucent pixels wouldn't have the filter applied.
885 bool apply_background_filters =
886 !frame->current_render_pass->has_transparent_background;
887 DCHECK(!frame->current_texture);
888
889 // TODO(ajuma): Add support for reference filters once
890 // FilterOperations::GetOutsets supports reference filters.
891 if (apply_background_filters && quad->background_filters.HasReferenceFilter())
892 apply_background_filters = false;
893
894 // TODO(danakj): Do a single readback for both the surface and replica and
895 // cache the filtered results (once filter textures are not reused).
896 gfx::Rect window_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect(
897 contents_device_transform, SharedGeometryQuad().BoundingBox()));
898
899 int top, right, bottom, left;
900 quad->background_filters.GetOutsets(&top, &right, &bottom, &left);
901 window_rect.Inset(-left, -top, -right, -bottom);
902
903 window_rect.Intersect(
904 MoveFromDrawToWindowSpace(frame->current_render_pass->output_rect));
905
906 scoped_ptr<ScopedResource> device_background_texture =
907 ScopedResource::Create(resource_provider_);
908 // CopyTexImage2D fails when called on a texture having immutable storage.
909 device_background_texture->Allocate(
910 window_rect.size(), ResourceProvider::TextureHintDefault, RGBA_8888);
911 {
912 ResourceProvider::ScopedWriteLockGL lock(resource_provider_,
913 device_background_texture->id());
914 GetFramebufferTexture(
915 lock.texture_id(), device_background_texture->format(), window_rect);
916 }
917
918 skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter(
919 quad->background_filters, device_background_texture->size());
920
921 skia::RefPtr<SkImage> filtered_device_background;
922 if (apply_background_filters) {
923 filtered_device_background =
924 ApplyImageFilter(ScopedUseGrContext::Create(this, frame),
925 resource_provider_,
926 quad->rect.origin(),
927 quad->filters_scale,
928 filter.get(),
929 device_background_texture.get());
930 }
931 *background_changed = (filtered_device_background != NULL);
932 956
933 int filtered_device_background_texture_id = 0; 957 int filtered_device_background_texture_id = 0;
934 scoped_ptr<ResourceProvider::ScopedReadLockGL> lock; 958 scoped_ptr<ResourceProvider::ScopedReadLockGL> lock;
935 if (filtered_device_background) { 959 if (filtered_device_background) {
936 GrTexture* texture = filtered_device_background->getTexture(); 960 GrTexture* texture = filtered_device_background->getTexture();
937 filtered_device_background_texture_id = texture->getTextureHandle(); 961 filtered_device_background_texture_id = texture->getTextureHandle();
938 } else { 962 } else {
939 lock.reset(new ResourceProvider::ScopedReadLockGL( 963 lock.reset(new ResourceProvider::ScopedReadLockGL(
940 resource_provider_, device_background_texture->id())); 964 resource_provider_, device_background_texture->id()));
941 filtered_device_background_texture_id = lock->texture_id(); 965 filtered_device_background_texture_id = lock->texture_id();
(...skipping 17 matching lines...) Expand all
959 QuadRectTransform( 983 QuadRectTransform(
960 &device_to_framebuffer_transform, gfx::Transform(), quad->rect); 984 &device_to_framebuffer_transform, gfx::Transform(), quad->rect);
961 device_to_framebuffer_transform.PreconcatTransform( 985 device_to_framebuffer_transform.PreconcatTransform(
962 contents_device_transform_inverse); 986 contents_device_transform_inverse);
963 987
964 #ifndef NDEBUG 988 #ifndef NDEBUG
965 GLC(gl_, gl_->ClearColor(0, 0, 1, 1)); 989 GLC(gl_, gl_->ClearColor(0, 0, 1, 1));
966 gl_->Clear(GL_COLOR_BUFFER_BIT); 990 gl_->Clear(GL_COLOR_BUFFER_BIT);
967 #endif 991 #endif
968 992
969 // The filtered_deveice_background_texture is oriented the same as the frame 993 // The background_texture is oriented the same as the frame buffer.
970 // buffer. The transform we are copying with has a vertical flip, as well as 994 // The transform we are copying with has a vertical flip, as well as
971 // the |device_to_framebuffer_transform|, which cancel each other out. So do 995 // the |device_to_framebuffer_transform|, which cancel each other out. So do
972 // not flip the contents in the shader to maintain orientation. 996 // not flip the contents in the shader to maintain orientation.
973 bool flip_vertically = false; 997 bool flip_vertically = false;
974 998
975 CopyTextureToFramebuffer(frame, 999 CopyTextureToFramebuffer(frame,
976 filtered_device_background_texture_id, 1000 filtered_device_background_texture_id,
977 window_rect, 1001 backdrop_bounding_rect,
978 device_to_framebuffer_transform, 1002 device_to_framebuffer_transform,
979 flip_vertically); 1003 flip_vertically);
980 } 1004 }
981 1005
982 UseRenderPass(frame, target_render_pass); 1006 UseRenderPass(frame, target_render_pass);
983 1007
984 if (!using_background_texture) 1008 if (!using_background_texture)
985 return nullptr; 1009 return nullptr;
986 return background_texture.Pass(); 1010 return background_texture.Pass();
987 } 1011 }
(...skipping 14 matching lines...) Expand all
1002 frame->window_matrix * frame->projection_matrix * quad_rect_matrix; 1026 frame->window_matrix * frame->projection_matrix * quad_rect_matrix;
1003 contents_device_transform.FlattenTo2d(); 1027 contents_device_transform.FlattenTo2d();
1004 1028
1005 // Can only draw surface if device matrix is invertible. 1029 // Can only draw surface if device matrix is invertible.
1006 gfx::Transform contents_device_transform_inverse( 1030 gfx::Transform contents_device_transform_inverse(
1007 gfx::Transform::kSkipInitialization); 1031 gfx::Transform::kSkipInitialization);
1008 if (!contents_device_transform.GetInverse(&contents_device_transform_inverse)) 1032 if (!contents_device_transform.GetInverse(&contents_device_transform_inverse))
1009 return; 1033 return;
1010 1034
1011 bool need_background_texture = !ShouldApplyBlendModeUsingBlendFunc(quad) || 1035 bool need_background_texture = !ShouldApplyBlendModeUsingBlendFunc(quad) ||
1012 !quad->background_filters.IsEmpty(); 1036 ShouldApplyBackgroundFilters(frame, quad);
1013 bool background_changed = false; 1037
1014 scoped_ptr<ScopedResource> background_texture; 1038 scoped_ptr<ScopedResource> background_texture;
1015 if (need_background_texture) { 1039 if (need_background_texture) {
1016 // The pixels from the filtered background should completely replace the 1040 // The pixels from the filtered background should completely replace the
1017 // current pixel values. 1041 // current pixel values.
1018 bool disable_blending = blend_enabled(); 1042 bool disable_blending = blend_enabled();
1019 if (disable_blending) 1043 if (disable_blending)
1020 SetBlendEnabled(false); 1044 SetBlendEnabled(false);
1021 1045
1022 background_texture = 1046 // Compute a bounding box around the pixels that will be visible through
1023 GetBackgroundWithFilters(frame, 1047 // the quad.
1024 quad, 1048 gfx::Rect backdrop_rect = GetBackdropBoundingBoxForRenderPassQuad(
1025 contents_device_transform, 1049 frame, quad, contents_device_transform);
1026 contents_device_transform_inverse, 1050
1027 &background_changed); 1051 // Read the pixels in the bounding box into a buffer R.
1052 scoped_ptr<ScopedResource> scoped_background_texture =
1053 GetBackdropTexture(backdrop_rect);
1054
1055 skia::RefPtr<SkImage> background_with_filters;
1056 if (ShouldApplyBackgroundFilters(frame, quad)) {
1057 // Apply the background filters to R, so that it is applied in the pixels'
1058 // coordinate space.
1059 background_with_filters =
1060 ApplyBackgroundFilters(frame, quad, scoped_background_texture.get());
1061 }
1062 // Apply the quad's inverse transform to map the pixels in R into the
1063 // quad's content space. This implicitly clips R by the content bounds of
1064 // the quad since the destination texture has bounds matching the quad's
1065 // content.
1066 background_texture = ApplyInverseTransformForBackgroundFilters(
1067 frame,
1068 quad,
1069 contents_device_transform_inverse,
1070 scoped_background_texture.get(),
1071 background_with_filters,
1072 backdrop_rect);
1028 1073
1029 if (disable_blending) 1074 if (disable_blending)
1030 SetBlendEnabled(true); 1075 SetBlendEnabled(true);
1031 } 1076 }
1032 1077
1033 // TODO(senorblanco): Cache this value so that we don't have to do it for both 1078 // TODO(senorblanco): Cache this value so that we don't have to do it for both
1034 // the surface and its replica. Apply filters to the contents texture. 1079 // the surface and its replica. Apply filters to the contents texture.
1035 skia::RefPtr<SkImage> filter_bitmap; 1080 skia::RefPtr<SkImage> filter_bitmap;
1036 SkScalar color_matrix[20]; 1081 SkScalar color_matrix[20];
1037 bool use_color_matrix = false; 1082 bool use_color_matrix = false;
(...skipping 18 matching lines...) Expand all
1056 ApplyImageFilter(ScopedUseGrContext::Create(this, frame), 1101 ApplyImageFilter(ScopedUseGrContext::Create(this, frame),
1057 resource_provider_, 1102 resource_provider_,
1058 quad->rect.origin(), 1103 quad->rect.origin(),
1059 quad->filters_scale, 1104 quad->filters_scale,
1060 filter.get(), 1105 filter.get(),
1061 contents_texture); 1106 contents_texture);
1062 } 1107 }
1063 } 1108 }
1064 } 1109 }
1065 1110
1111 // If blending is applied using shaders, the background texture with
1112 // filters will be used as backdrop for blending operation, so we don't
1113 // need to copy it to the frame buffer.
1066 if (background_texture && !ShouldApplyBlendModeUsingBlendFunc(quad)) { 1114 if (background_texture && !ShouldApplyBlendModeUsingBlendFunc(quad)) {
1067 filter_bitmap = 1115 filter_bitmap =
1068 ApplyBlendModeWithBackdrop(ScopedUseGrContext::Create(this, frame), 1116 ApplyBlendModeWithBackdrop(ScopedUseGrContext::Create(this, frame),
1069 resource_provider_, 1117 resource_provider_,
1070 filter_bitmap, 1118 filter_bitmap,
1071 contents_texture, 1119 contents_texture,
1072 background_texture.get(), 1120 background_texture.get(),
1073 quad->shared_quad_state->blend_mode); 1121 quad->shared_quad_state->blend_mode);
1074 } 1122 } else if (background_texture) {
1075 1123 // Draw the background texture if it has some filters applied.
1076 // Draw the background texture if it has some filters applied. 1124 DCHECK(ShouldApplyBackgroundFilters(frame, quad));
1077 if (background_texture && background_changed) {
1078 DCHECK(background_texture->size() == quad->rect.size()); 1125 DCHECK(background_texture->size() == quad->rect.size());
1079 ResourceProvider::ScopedReadLockGL lock(resource_provider_, 1126 ResourceProvider::ScopedReadLockGL lock(resource_provider_,
1080 background_texture->id()); 1127 background_texture->id());
1081 1128
1082 // The background_texture is oriented the same as the frame buffer. The 1129 // The background_texture is oriented the same as the frame buffer. The
1083 // transform we are copying with has a vertical flip, so flip the contents 1130 // transform we are copying with has a vertical flip, so flip the contents
1084 // in the shader to maintain orientation 1131 // in the shader to maintain orientation
1085 bool flip_vertically = true; 1132 bool flip_vertically = true;
1086 1133
1087 CopyTextureToFramebuffer(frame, 1134 CopyTextureToFramebuffer(frame,
(...skipping 2132 matching lines...) Expand 10 before | Expand all | Expand 10 after
3220 context_support_->ScheduleOverlayPlane( 3267 context_support_->ScheduleOverlayPlane(
3221 overlay.plane_z_order, 3268 overlay.plane_z_order,
3222 overlay.transform, 3269 overlay.transform,
3223 pending_overlay_resources_.back()->texture_id(), 3270 pending_overlay_resources_.back()->texture_id(),
3224 overlay.display_rect, 3271 overlay.display_rect,
3225 overlay.uv_rect); 3272 overlay.uv_rect);
3226 } 3273 }
3227 } 3274 }
3228 3275
3229 } // namespace cc 3276 } // namespace cc
OLDNEW
« 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