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 832 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |