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 <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
60 #include "third_party/skia/include/gpu/gl/GrGLTypes.h" | 60 #include "third_party/skia/include/gpu/gl/GrGLTypes.h" |
61 #include "ui/gfx/geometry/quad_f.h" | 61 #include "ui/gfx/geometry/quad_f.h" |
62 #include "ui/gfx/geometry/rect_conversions.h" | 62 #include "ui/gfx/geometry/rect_conversions.h" |
63 #include "ui/gfx/skia_util.h" | 63 #include "ui/gfx/skia_util.h" |
64 | 64 |
65 using gpu::gles2::GLES2Interface; | 65 using gpu::gles2::GLES2Interface; |
66 | 66 |
67 namespace cc { | 67 namespace cc { |
68 namespace { | 68 namespace { |
69 | 69 |
70 class ScopedTextureDeleter { | |
71 public: | |
72 ScopedTextureDeleter(GLuint texture, gpu::gles2::GLES2Interface* gl) | |
73 : texture_(texture), gl_(gl) {} | |
74 ~ScopedTextureDeleter() { gl_->DeleteTextures(1, &texture_); } | |
75 | |
76 private: | |
77 GLuint texture_; | |
78 gpu::gles2::GLES2Interface* gl_; | |
79 }; | |
80 | |
81 class ScopedFramebufferDeleter { | |
82 public: | |
83 ScopedFramebufferDeleter(GLuint fbo, gpu::gles2::GLES2Interface* gl) | |
84 : fbo_(fbo), gl_(gl) {} | |
85 ~ScopedFramebufferDeleter() { gl_->DeleteFramebuffers(1, &fbo_); } | |
86 | |
87 private: | |
88 GLuint fbo_; | |
89 gpu::gles2::GLES2Interface* gl_; | |
90 }; | |
91 | |
70 Float4 UVTransform(const TextureDrawQuad* quad) { | 92 Float4 UVTransform(const TextureDrawQuad* quad) { |
71 gfx::PointF uv0 = quad->uv_top_left; | 93 gfx::PointF uv0 = quad->uv_top_left; |
72 gfx::PointF uv1 = quad->uv_bottom_right; | 94 gfx::PointF uv1 = quad->uv_bottom_right; |
73 Float4 xform = {{uv0.x(), uv0.y(), uv1.x() - uv0.x(), uv1.y() - uv0.y()}}; | 95 Float4 xform = {{uv0.x(), uv0.y(), uv1.x() - uv0.x(), uv1.y() - uv0.y()}}; |
74 if (quad->y_flipped) { | 96 if (quad->y_flipped) { |
75 xform.data[1] = 1.0f - xform.data[1]; | 97 xform.data[1] = 1.0f - xform.data[1]; |
76 xform.data[3] = -xform.data[3]; | 98 xform.data[3] = -xform.data[3]; |
77 } | 99 } |
78 return xform; | 100 return xform; |
79 } | 101 } |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
158 | 180 |
159 // Required Inputs. | 181 // Required Inputs. |
160 const RenderPassDrawQuad* quad = nullptr; | 182 const RenderPassDrawQuad* quad = nullptr; |
161 const Resource* contents_texture = nullptr; | 183 const Resource* contents_texture = nullptr; |
162 const gfx::QuadF* clip_region = nullptr; | 184 const gfx::QuadF* clip_region = nullptr; |
163 bool flip_texture = false; | 185 bool flip_texture = false; |
164 | 186 |
165 gfx::Transform window_matrix; | 187 gfx::Transform window_matrix; |
166 gfx::Transform projection_matrix; | 188 gfx::Transform projection_matrix; |
167 | 189 |
168 // |frame| is needed for background effects. | 190 // |frame| is used to restore the current render pass. |frame| is also needed |
191 // for background effects. If |frame| is not present, nothing happens. | |
169 DirectRenderer::DrawingFrame* frame = nullptr; | 192 DirectRenderer::DrawingFrame* frame = nullptr; |
170 | 193 |
171 // Whether the texture to be sampled from needs to be flipped. | 194 // Whether the texture to be sampled from needs to be flipped. |
172 bool source_needs_flip = false; | 195 bool source_needs_flip = false; |
173 | 196 |
174 float edge[24]; | 197 float edge[24]; |
175 SkScalar color_matrix[20]; | 198 SkScalar color_matrix[20]; |
176 | 199 |
177 // Blending refers to modifications to the backdrop. | 200 // Blending refers to modifications to the backdrop. |
178 bool use_shaders_for_blending = false; | 201 bool use_shaders_for_blending = false; |
(...skipping 2511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2690 | 2713 |
2691 ScheduleCALayers(frame); | 2714 ScheduleCALayers(frame); |
2692 ScheduleOverlays(frame); | 2715 ScheduleOverlays(frame); |
2693 } | 2716 } |
2694 | 2717 |
2695 void GLRenderer::FinishDrawingQuadList() { | 2718 void GLRenderer::FinishDrawingQuadList() { |
2696 FlushTextureQuadCache(SHARED_BINDING); | 2719 FlushTextureQuadCache(SHARED_BINDING); |
2697 } | 2720 } |
2698 | 2721 |
2699 bool GLRenderer::FlippedFramebuffer(const DrawingFrame* frame) const { | 2722 bool GLRenderer::FlippedFramebuffer(const DrawingFrame* frame) const { |
2723 if (frame == force_drawing_frame_framebuffer_flipped_) | |
2724 return true; | |
2700 if (frame->current_render_pass != frame->root_render_pass) | 2725 if (frame->current_render_pass != frame->root_render_pass) |
2701 return true; | 2726 return true; |
2702 return FlippedRootFramebuffer(); | 2727 return FlippedRootFramebuffer(); |
2703 } | 2728 } |
2704 | 2729 |
2705 bool GLRenderer::FlippedRootFramebuffer() const { | 2730 bool GLRenderer::FlippedRootFramebuffer() const { |
2706 // GL is normally flipped, so a flipped output results in an unflipping. | 2731 // GL is normally flipped, so a flipped output results in an unflipping. |
2707 return !output_surface_->capabilities().flipped_output_surface; | 2732 return !output_surface_->capabilities().flipped_output_surface; |
2708 } | 2733 } |
2709 | 2734 |
(...skipping 1028 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3738 } | 3763 } |
3739 } | 3764 } |
3740 | 3765 |
3741 bool GLRenderer::IsContextLost() { | 3766 bool GLRenderer::IsContextLost() { |
3742 return gl_->GetGraphicsResetStatusKHR() != GL_NO_ERROR; | 3767 return gl_->GetGraphicsResetStatusKHR() != GL_NO_ERROR; |
3743 } | 3768 } |
3744 | 3769 |
3745 void GLRenderer::ScheduleCALayers(DrawingFrame* frame) { | 3770 void GLRenderer::ScheduleCALayers(DrawingFrame* frame) { |
3746 scoped_refptr<CALayerOverlaySharedState> shared_state; | 3771 scoped_refptr<CALayerOverlaySharedState> shared_state; |
3747 size_t copied_render_pass_count = 0; | 3772 size_t copied_render_pass_count = 0; |
3748 for (const CALayerOverlay& ca_layer_overlay : frame->ca_layer_overlay_list) { | 3773 for (CALayerOverlay& ca_layer_overlay : frame->ca_layer_overlay_list) { |
3749 if (!overlay_resource_pool_) { | 3774 if (!overlay_resource_pool_) { |
3750 overlay_resource_pool_ = ResourcePool::CreateForGpuMemoryBufferResources( | 3775 overlay_resource_pool_ = ResourcePool::CreateForGpuMemoryBufferResources( |
3751 resource_provider_, base::ThreadTaskRunnerHandle::Get().get(), | 3776 resource_provider_, base::ThreadTaskRunnerHandle::Get().get(), |
3752 gfx::BufferUsage::SCANOUT); | 3777 gfx::BufferUsage::SCANOUT); |
3753 } | 3778 } |
3754 | 3779 |
3755 ResourceId contents_resource_id = ca_layer_overlay.contents_resource_id; | 3780 ResourceId contents_resource_id = ca_layer_overlay.contents_resource_id; |
3756 Resource* resource = nullptr; | 3781 Resource* resource = nullptr; |
3757 // Some CALayers require a final round of processing. | 3782 // Some CALayers require a final round of processing. |
3758 if (ca_layer_overlay.render_pass_id.IsValid()) { | 3783 if (ca_layer_overlay.rpdq.get()) { |
3759 CopyRenderPassToOverlayResource(ca_layer_overlay.render_pass_id, | 3784 CopyRenderPassDrawQuadToOverlayResource(&ca_layer_overlay, &resource, |
3760 &resource); | 3785 frame); |
ccameron
2016/08/04 01:46:01
Rather than updating the CALayerOverlay parameters
erikchen
2016/08/05 17:15:06
Done.
| |
3761 contents_resource_id = resource->id(); | 3786 if (resource) { |
3762 ++copied_render_pass_count; | 3787 contents_resource_id = resource->id(); |
3788 ++copied_render_pass_count; | |
3789 } | |
3763 } | 3790 } |
3764 | 3791 |
3765 unsigned texture_id = 0; | 3792 unsigned texture_id = 0; |
3766 if (contents_resource_id) { | 3793 if (contents_resource_id) { |
3767 pending_overlay_resources_.push_back( | 3794 pending_overlay_resources_.push_back( |
3768 base::WrapUnique(new ResourceProvider::ScopedReadLockGL( | 3795 base::WrapUnique(new ResourceProvider::ScopedReadLockGL( |
3769 resource_provider_, contents_resource_id))); | 3796 resource_provider_, contents_resource_id))); |
3770 texture_id = pending_overlay_resources_.back()->texture_id(); | 3797 texture_id = pending_overlay_resources_.back()->texture_id(); |
3771 | 3798 |
3772 if (resource) { | 3799 if (resource) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3813 effect.amount = filter_effect.amount; | 3840 effect.amount = filter_effect.amount; |
3814 effect.drop_shadow_offset_x = filter_effect.drop_shadow_offset.x(); | 3841 effect.drop_shadow_offset_x = filter_effect.drop_shadow_offset.x(); |
3815 effect.drop_shadow_offset_y = filter_effect.drop_shadow_offset.y(); | 3842 effect.drop_shadow_offset_y = filter_effect.drop_shadow_offset.y(); |
3816 | 3843 |
3817 static_assert(sizeof(GLuint) == sizeof(SkColor), | 3844 static_assert(sizeof(GLuint) == sizeof(SkColor), |
3818 "GLuint and SkColor must have the same size."); | 3845 "GLuint and SkColor must have the same size."); |
3819 effect.drop_shadow_color = | 3846 effect.drop_shadow_color = |
3820 static_cast<GLuint>(filter_effect.drop_shadow_color); | 3847 static_cast<GLuint>(filter_effect.drop_shadow_color); |
3821 } | 3848 } |
3822 | 3849 |
3823 gl_->ScheduleCALayerFilterEffectsCHROMIUM(effects.size(), effects.data()); | 3850 // TODO(erikchen): Remove all logic associated with |
3851 // ScheduleCALayerFilterEffectsCHROMIUM once the implementation of filter | |
3852 // effects for CA is fully functional. https://crbug.com/581526. | |
3853 // gl_->ScheduleCALayerFilterEffectsCHROMIUM(effects.size(), | |
3854 // effects.data()); | |
3824 } | 3855 } |
3825 gl_->ScheduleCALayerCHROMIUM( | 3856 gl_->ScheduleCALayerCHROMIUM( |
3826 texture_id, contents_rect, ca_layer_overlay.background_color, | 3857 texture_id, contents_rect, ca_layer_overlay.background_color, |
3827 ca_layer_overlay.edge_aa_mask, bounds_rect, filter); | 3858 ca_layer_overlay.edge_aa_mask, bounds_rect, filter); |
3828 } | 3859 } |
3829 | 3860 |
3830 // Take the number of copied render passes in this frame, and use 3 times that | 3861 // Take the number of copied render passes in this frame, and use 3 times that |
3831 // amount as the cache limit. | 3862 // amount as the cache limit. |
3832 if (overlay_resource_pool_) { | 3863 if (overlay_resource_pool_) { |
3833 overlay_resource_pool_->SetResourceUsageLimits( | 3864 overlay_resource_pool_->SetResourceUsageLimits( |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3879 source.reset(new ResourceProvider::ScopedReadLockGL( | 3910 source.reset(new ResourceProvider::ScopedReadLockGL( |
3880 resource_provider_, contents_texture->id())); | 3911 resource_provider_, contents_texture->id())); |
3881 source_texture = source->texture_id(); | 3912 source_texture = source->texture_id(); |
3882 } | 3913 } |
3883 gl_->CopySubTextureCHROMIUM(source_texture, destination.texture_id(), 0, 0, 0, | 3914 gl_->CopySubTextureCHROMIUM(source_texture, destination.texture_id(), 0, 0, 0, |
3884 0, contents_texture->size().width(), | 3915 0, contents_texture->size().width(), |
3885 contents_texture->size().height(), GL_TRUE, | 3916 contents_texture->size().height(), GL_TRUE, |
3886 GL_FALSE, GL_FALSE); | 3917 GL_FALSE, GL_FALSE); |
3887 } | 3918 } |
3888 | 3919 |
3920 // This function draws the RenderPassDrawQuad into a temporary | |
3921 // texture/framebuffer, and then copies the result into an IOSurface. | |
3922 void GLRenderer::CopyRenderPassDrawQuadToOverlayResource( | |
3923 CALayerOverlay* ca_layer_overlay, | |
3924 Resource** resource, | |
3925 DrawingFrame* external_frame) { | |
3926 ScopedResource* contents_texture = | |
3927 render_pass_textures_[ca_layer_overlay->rpdq->render_pass_id].get(); | |
3928 DCHECK(contents_texture); | |
3929 | |
3930 // The intermediary texture may need to be larger than the original content, | |
3931 // since the BLUR and DROP_SHADOW filter effects affect pixels outside the | |
3932 // original content. The exact size is computed within Skia, along with the | |
3933 // creation of |filter_image|. That computation requires that the |dst_rect| | |
3934 // parameter be configured. | |
3935 DrawRenderPassDrawQuadParams params; | |
3936 params.quad = ca_layer_overlay->rpdq.get(); | |
3937 params.flip_texture = true; | |
3938 params.contents_texture = contents_texture; | |
3939 | |
3940 SkMatrix scale_matrix; | |
3941 scale_matrix.setScale(params.quad->filters_scale.x(), | |
3942 params.quad->filters_scale.y()); | |
3943 gfx::Rect dst_rect = | |
3944 params.quad->filters.MapRect(params.quad->rect, scale_matrix); | |
3945 params.dst_rect.SetRect(static_cast<float>(dst_rect.x()), | |
3946 static_cast<float>(dst_rect.y()), | |
3947 static_cast<float>(dst_rect.width()), | |
3948 static_cast<float>(dst_rect.height())); | |
3949 | |
3950 if (!UpdateRPDQWithSkiaFilters(¶ms)) { | |
3951 return; | |
3952 } | |
3953 | |
3954 // |params.dst_rect| and |params.src_offset| now contain values that reflect a | |
3955 // potentially increased-size content area. | |
3956 gfx::RectF updated_dst_rect = params.dst_rect; | |
3957 gfx::Point updated_src_offset = params.src_offset; | |
3958 | |
3959 // Establish temp texture and fbo. | |
3960 GLuint temp_texture; | |
3961 GLuint temp_fbo; | |
3962 | |
3963 gl_->GenTextures(1, &temp_texture); | |
3964 ScopedTextureDeleter texture_deleter(temp_texture, gl_); | |
3965 gl_->BindTexture(GL_TEXTURE_2D, temp_texture); | |
3966 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
3967 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
3968 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
3969 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
3970 gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, updated_dst_rect.width(), | |
3971 updated_dst_rect.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, | |
3972 nullptr); | |
3973 | |
3974 gl_->GenFramebuffers(1, &temp_fbo); | |
3975 ScopedFramebufferDeleter framebuffer_deleter(temp_fbo, gl_); | |
3976 gl_->BindFramebuffer(GL_FRAMEBUFFER, temp_fbo); | |
3977 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | |
3978 temp_texture, 0); | |
3979 DCHECK(gl_->CheckFramebufferStatus(GL_FRAMEBUFFER) == | |
3980 GL_FRAMEBUFFER_COMPLETE); | |
3981 | |
3982 // Clear to 0 to ensure the background is transparent. | |
3983 gl_->ClearColor(0, 0, 0, 0); | |
3984 gl_->Clear(GL_COLOR_BUFFER_BIT); | |
3985 | |
3986 // Set up a new drawing context. The viewport should be the same size as | |
3987 // |temp_fbo|. Update the viewport using InitializeViewport(). This requires | |
3988 // creating a dummy DrawingFrame. This also calculates the projection and | |
3989 // window matrices. | |
3990 DrawingFrame frame; | |
3991 force_drawing_frame_framebuffer_flipped_ = &frame; | |
3992 gfx::Rect frame_rect = | |
3993 gfx::Rect(0, 0, updated_dst_rect.width(), updated_dst_rect.height()); | |
3994 InitializeViewport(&frame, frame_rect, frame_rect, frame_rect.size()); | |
3995 force_drawing_frame_framebuffer_flipped_ = nullptr; | |
3996 SetViewport(); | |
3997 params.projection_matrix = frame.projection_matrix; | |
3998 params.window_matrix = frame.window_matrix; | |
3999 | |
4000 // The SharedQuadState for the RenderPassDrawQuad needs to be updated to | |
4001 // reflect the new viewport. | |
4002 SharedQuadState sqs = *(ca_layer_overlay->rpdq->shared_quad_state); | |
4003 ca_layer_overlay->rpdq->shared_quad_state = &sqs; | |
4004 sqs.quad_to_target_transform = gfx::Transform(); | |
4005 sqs.quad_to_target_transform.Translate(-updated_dst_rect.x(), | |
4006 -updated_dst_rect.y()); | |
4007 | |
4008 // Perform basic initialization in the new viewport. | |
4009 if (!InitializeRPDQParameters(¶ms)) | |
4010 return; | |
4011 | |
4012 // Update |dst_rect| and |src_offset| with the values originally calculated | |
4013 // from Skia. | |
4014 params.dst_rect = updated_dst_rect; | |
4015 params.src_offset = updated_src_offset; | |
4016 | |
4017 UpdateRPDQTexturesForSampling(¶ms); | |
4018 UpdateRPDQBlendMode(¶ms); | |
4019 ChooseRPDQProgram(¶ms); | |
4020 UpdateRPDQUniforms(¶ms); | |
4021 | |
4022 // Prior to drawing, set up the destination framebuffer. | |
4023 gl_->BindFramebuffer(GL_FRAMEBUFFER, temp_fbo); | |
4024 DrawRPDQ(params); | |
ccameron
2016/08/04 01:46:01
I'll need to understand this a bit better, but, my
erikchen
2016/08/05 17:15:06
Your suggestion is sound. The new PS implements yo
| |
4025 | |
4026 // Copy from the temporary framebuffer into an overlay. | |
4027 *resource = overlay_resource_pool_->AcquireResource( | |
4028 gfx::Size(updated_dst_rect.width(), updated_dst_rect.height()), | |
4029 ResourceFormat::RGBA_8888); | |
4030 ResourceProvider::ScopedWriteLockGL destination(resource_provider_, | |
4031 (*resource)->id(), false); | |
4032 gl_->CopySubTextureCHROMIUM(temp_texture, destination.texture_id(), 0, 0, 0, | |
4033 0, updated_dst_rect.width(), | |
4034 updated_dst_rect.height(), GL_TRUE, GL_FALSE, | |
4035 GL_FALSE); | |
4036 | |
4037 // Update the CALayerOverlaySharedState to reflect the new size and translate | |
4038 // of the overlay. | |
4039 ca_layer_overlay->bounds_rect = | |
4040 gfx::RectF(0, 0, updated_dst_rect.width(), updated_dst_rect.height()); | |
4041 scoped_refptr<CALayerOverlaySharedState> shared_state = | |
4042 (new CALayerOverlaySharedState); | |
4043 *shared_state = *ca_layer_overlay->shared_state; | |
4044 ca_layer_overlay->shared_state = shared_state; | |
ccameron
2016/08/04 01:46:01
This doesn't strike me as correct. What if shared_
erikchen
2016/08/05 17:15:06
Right. This should have been preTranslate.
| |
4045 float x_translate = shared_state->transform.getFloat(0, 3); | |
4046 float y_translate = shared_state->transform.getFloat(1, 3); | |
4047 float z_translate = shared_state->transform.getFloat(2, 3); | |
4048 shared_state->transform.setTranslate(x_translate + updated_dst_rect.x(), | |
4049 y_translate + updated_dst_rect.y(), | |
4050 z_translate); | |
4051 } | |
4052 | |
3889 } // namespace cc | 4053 } // namespace cc |
OLD | NEW |