Chromium Code Reviews| 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 |