OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |