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

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