@@ -160,11 +160,11 @@ struct DrawRenderPassDrawQuadParams {
160
160
const Resource* contents_texture = nullptr ;
161
161
const gfx::QuadF* clip_region = nullptr ;
162
162
bool flip_texture = false ;
163
-
164
163
gfx::Transform window_matrix;
165
164
gfx::Transform projection_matrix;
165
+ gfx::Transform quad_to_target_transform;
166
166
167
- // |frame| is needed for background effects.
167
+ // |frame| is only used for background effects.
168
168
DirectRenderer::DrawingFrame* frame = nullptr ;
169
169
170
170
// Whether the texture to be sampled from needs to be flipped.
@@ -215,6 +215,7 @@ struct DrawRenderPassDrawQuadParams {
215
215
bool use_color_matrix = false ;
216
216
217
217
gfx::QuadF surface_quad;
218
+
218
219
gfx::Transform contents_device_transform;
219
220
};
220
221
@@ -1068,6 +1069,8 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
1068
1069
1069
1070
void GLRenderer::DrawRenderPassQuadInternal (
1070
1071
DrawRenderPassDrawQuadParams* params) {
1072
+ params->quad_to_target_transform =
1073
+ params->quad ->shared_quad_state ->quad_to_target_transform ;
1071
1074
if (!InitializeRPDQParameters (params))
1072
1075
return ;
1073
1076
UpdateRPDQShadersForBlending (params);
@@ -1093,8 +1096,7 @@ bool GLRenderer::InitializeRPDQParameters(
1093
1096
static_cast <float >(dst_rect.width ()),
1094
1097
static_cast <float >(dst_rect.height ()));
1095
1098
gfx::Transform quad_rect_matrix;
1096
- QuadRectTransform (&quad_rect_matrix,
1097
- quad->shared_quad_state ->quad_to_target_transform ,
1099
+ QuadRectTransform (&quad_rect_matrix, params->quad_to_target_transform ,
1098
1100
params->dst_rect );
1099
1101
params->contents_device_transform =
1100
1102
params->window_matrix * params->projection_matrix * quad_rect_matrix;
@@ -1217,8 +1219,7 @@ bool GLRenderer::UpdateRPDQWithSkiaFilters(
1217
1219
if (clip_rect.IsEmpty ()) {
1218
1220
clip_rect = current_draw_rect_;
1219
1221
}
1220
- gfx::Transform transform =
1221
- quad->shared_quad_state ->quad_to_target_transform ;
1222
+ gfx::Transform transform = params->quad_to_target_transform ;
1222
1223
gfx::QuadF clip_quad = gfx::QuadF (gfx::RectF (clip_rect));
1223
1224
gfx::QuadF local_clip = MapQuadToLocalSpace (transform, clip_quad);
1224
1225
params->dst_rect .Intersect (local_clip.BoundingBox ());
@@ -1499,8 +1500,7 @@ void GLRenderer::UpdateRPDQUniforms(DrawRenderPassDrawQuadParams* params) {
1499
1500
}
1500
1501
1501
1502
void GLRenderer::DrawRPDQ (const DrawRenderPassDrawQuadParams& params) {
1502
- DrawQuadGeometry (params.projection_matrix ,
1503
- params.quad ->shared_quad_state ->quad_to_target_transform ,
1503
+ DrawQuadGeometry (params.projection_matrix , params.quad_to_target_transform ,
1504
1504
params.dst_rect , params.locations .matrix );
1505
1505
1506
1506
// Flush the compositor context before the filter bitmap goes out of
@@ -2728,6 +2728,8 @@ void GLRenderer::FinishDrawingQuadList() {
2728
2728
}
2729
2729
2730
2730
bool GLRenderer::FlippedFramebuffer (const DrawingFrame* frame) const {
2731
+ if (force_drawing_frame_framebuffer_unflipped_)
2732
+ return false ;
2731
2733
if (frame->current_render_pass != frame->root_render_pass )
2732
2734
return true ;
2733
2735
return FlippedRootFramebuffer ();
@@ -3777,10 +3779,11 @@ void GLRenderer::ScheduleCALayers(DrawingFrame* frame) {
3777
3779
scoped_refptr<CALayerOverlaySharedState> shared_state;
3778
3780
size_t copied_render_pass_count = 0 ;
3779
3781
for (const CALayerOverlay& ca_layer_overlay : frame->ca_layer_overlay_list ) {
3780
- if (!overlay_resource_pool_) {
3781
- overlay_resource_pool_ = ResourcePool::CreateForGpuMemoryBufferResources (
3782
- resource_provider_, base::ThreadTaskRunnerHandle::Get ().get (),
3783
- gfx::BufferUsage::SCANOUT);
3782
+ if (ca_layer_overlay.rpdq ) {
3783
+ ScheduleRenderPassDrawQuad (&ca_layer_overlay, frame);
3784
+ shared_state = nullptr ;
3785
+ ++copied_render_pass_count;
3786
+ continue ;
3784
3787
}
3785
3788
3786
3789
ResourceId contents_resource_id = ca_layer_overlay.contents_resource_id ;
@@ -3854,4 +3857,184 @@ void GLRenderer::ScheduleOverlays(DrawingFrame* frame) {
3854
3857
}
3855
3858
}
3856
3859
3860
+ // This function draws the RenderPassDrawQuad into a temporary
3861
+ // texture/framebuffer, and then copies the result into an IOSurface. The
3862
+ // inefficient (but simple) way to do this would be to:
3863
+ // 1. Allocate a framebuffer the size of the screen.
3864
+ // 2. Draw using all the normal RPDQ draw logic.
3865
+ //
3866
+ // Instead, this method does the following:
3867
+ // 1. Configure parameters as if drawing to a framebuffer the size of the
3868
+ // screen. This reuses most of the RPDQ draw logic.
3869
+ // 2. Update parameters to draw into a framebuffer only as large as needed.
3870
+ // 3. Fix shader uniforms that were broken by (2).
3871
+ //
3872
+ // Then:
3873
+ // 4. Allocate an IOSurface as the drawing destination.
3874
+ // 5. Draw the RPDQ.
3875
+ void GLRenderer::CopyRenderPassDrawQuadToOverlayResource (
3876
+ const CALayerOverlay* ca_layer_overlay,
3877
+ Resource** resource,
3878
+ DrawingFrame* external_frame,
3879
+ gfx::RectF* new_bounds) {
3880
+ ScopedResource* contents_texture =
3881
+ render_pass_textures_[ca_layer_overlay->rpdq ->render_pass_id ].get ();
3882
+ DCHECK (contents_texture);
3883
+
3884
+ // Configure parameters as if drawing to a framebuffer the size of the
3885
+ // screen.
3886
+ DrawRenderPassDrawQuadParams params;
3887
+ params.quad = ca_layer_overlay->rpdq ;
3888
+ params.flip_texture = true ;
3889
+ params.contents_texture = contents_texture;
3890
+ params.quad_to_target_transform =
3891
+ params.quad ->shared_quad_state ->quad_to_target_transform ;
3892
+
3893
+ // Calculate projection and window matrices using InitializeViewport(). This
3894
+ // requires creating a dummy DrawingFrame.
3895
+ {
3896
+ DrawingFrame frame;
3897
+ gfx::Rect frame_rect = external_frame->device_viewport_rect ;
3898
+ force_drawing_frame_framebuffer_unflipped_ = true ;
3899
+ InitializeViewport (&frame, frame_rect, frame_rect, frame_rect.size ());
3900
+ force_drawing_frame_framebuffer_unflipped_ = false ;
3901
+ params.projection_matrix = frame.projection_matrix ;
3902
+ params.window_matrix = frame.window_matrix ;
3903
+ }
3904
+
3905
+ // Perform basic initialization with the screen-sized viewport.
3906
+ if (!InitializeRPDQParameters (¶ms))
3907
+ return ;
3908
+
3909
+ if (!UpdateRPDQWithSkiaFilters (¶ms))
3910
+ return ;
3911
+
3912
+ // |params.dst_rect| now contain values that reflect a potentially increased
3913
+ // size quad.
3914
+ gfx::RectF updated_dst_rect = params.dst_rect ;
3915
+ *new_bounds = updated_dst_rect;
3916
+
3917
+ // Calculate new projection and window matrices for a minimally sized viewport
3918
+ // using InitializeViewport(). This requires creating a dummy DrawingFrame.
3919
+ {
3920
+ DrawingFrame frame;
3921
+ force_drawing_frame_framebuffer_unflipped_ = true ;
3922
+ gfx::Rect frame_rect =
3923
+ gfx::Rect (0 , 0 , updated_dst_rect.width (), updated_dst_rect.height ());
3924
+ InitializeViewport (&frame, frame_rect, frame_rect, frame_rect.size ());
3925
+ force_drawing_frame_framebuffer_unflipped_ = false ;
3926
+ params.projection_matrix = frame.projection_matrix ;
3927
+ params.window_matrix = frame.window_matrix ;
3928
+ }
3929
+
3930
+ // Calculate a new quad_to_target_transform.
3931
+ params.quad_to_target_transform = gfx::Transform ();
3932
+ params.quad_to_target_transform .Translate (-updated_dst_rect.x (),
3933
+ -updated_dst_rect.y ());
3934
+
3935
+ // Antialiasing works by fading out content that is close to the edge of the
3936
+ // viewport. All of these values need to be recalculated.
3937
+ if (params.use_aa ) {
3938
+ current_window_space_viewport_ =
3939
+ gfx::Rect (0 , 0 , updated_dst_rect.width (), updated_dst_rect.height ());
3940
+ gfx::Transform quad_rect_matrix;
3941
+ QuadRectTransform (&quad_rect_matrix, params.quad_to_target_transform ,
3942
+ updated_dst_rect);
3943
+ params.contents_device_transform =
3944
+ params.window_matrix * params.projection_matrix * quad_rect_matrix;
3945
+ bool clipped = false ;
3946
+ params.contents_device_transform .FlattenTo2d ();
3947
+ gfx::QuadF device_layer_quad = MathUtil::MapQuad (
3948
+ params.contents_device_transform , SharedGeometryQuad (), &clipped);
3949
+ LayerQuad device_layer_edges (device_layer_quad);
3950
+ InflateAntiAliasingDistances (device_layer_quad, &device_layer_edges,
3951
+ params.edge );
3952
+ }
3953
+
3954
+ // Establish destination texture.
3955
+ *resource = overlay_resource_pool_->AcquireResource (
3956
+ gfx::Size (updated_dst_rect.width (), updated_dst_rect.height ()),
3957
+ ResourceFormat::RGBA_8888);
3958
+ ResourceProvider::ScopedWriteLockGL destination (resource_provider_,
3959
+ (*resource)->id (), false );
3960
+ GLuint temp_fbo;
3961
+
3962
+ gl_->GenFramebuffers (1 , &temp_fbo);
3963
+ gl_->BindFramebuffer (GL_FRAMEBUFFER, temp_fbo);
3964
+ gl_->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
3965
+ destination.target (), destination.texture_id (), 0 );
3966
+ DCHECK (gl_->CheckFramebufferStatus (GL_FRAMEBUFFER) ==
3967
+ GL_FRAMEBUFFER_COMPLETE);
3968
+
3969
+ // Clear to 0 to ensure the background is transparent.
3970
+ gl_->ClearColor (0 , 0 , 0 , 0 );
3971
+ gl_->Clear (GL_COLOR_BUFFER_BIT);
3972
+
3973
+ UpdateRPDQTexturesForSampling (¶ms);
3974
+ UpdateRPDQBlendMode (¶ms);
3975
+ ChooseRPDQProgram (¶ms);
3976
+ UpdateRPDQUniforms (¶ms);
3977
+
3978
+ // Prior to drawing, set up the destination framebuffer and viewport.
3979
+ gl_->BindFramebuffer (GL_FRAMEBUFFER, temp_fbo);
3980
+ gl_->Viewport (0 , 0 , updated_dst_rect.width (), updated_dst_rect.height ());
3981
+
3982
+ DrawRPDQ (params);
3983
+ gl_->DeleteFramebuffers (1 , &temp_fbo);
3984
+ }
3985
+
3986
+ void GLRenderer::ScheduleRenderPassDrawQuad (
3987
+ const CALayerOverlay* ca_layer_overlay,
3988
+ DrawingFrame* external_frame) {
3989
+ DCHECK (ca_layer_overlay->rpdq );
3990
+
3991
+ if (!overlay_resource_pool_) {
3992
+ overlay_resource_pool_ = ResourcePool::CreateForGpuMemoryBufferResources (
3993
+ resource_provider_, base::ThreadTaskRunnerHandle::Get ().get (),
3994
+ gfx::BufferUsage::SCANOUT);
3995
+ }
3996
+
3997
+ Resource* resource = nullptr ;
3998
+ gfx::RectF new_bounds;
3999
+ CopyRenderPassDrawQuadToOverlayResource (ca_layer_overlay, &resource,
4000
+ external_frame, &new_bounds);
4001
+ if (!resource || !resource->id ())
4002
+ return ;
4003
+
4004
+ pending_overlay_resources_.push_back (
4005
+ base::WrapUnique (new ResourceProvider::ScopedReadLockGL (
4006
+ resource_provider_, resource->id ())));
4007
+ unsigned texture_id = pending_overlay_resources_.back ()->texture_id ();
4008
+
4009
+ // Once a resource is released, it is marked as "busy". It will be
4010
+ // available for reuse after the ScopedReadLockGL is destroyed.
4011
+ overlay_resource_pool_->ReleaseResource (resource);
4012
+
4013
+ GLfloat contents_rect[4 ] = {
4014
+ ca_layer_overlay->contents_rect .x (), ca_layer_overlay->contents_rect .y (),
4015
+ ca_layer_overlay->contents_rect .width (),
4016
+ ca_layer_overlay->contents_rect .height (),
4017
+ };
4018
+ GLfloat bounds_rect[4 ] = {
4019
+ new_bounds.x (), new_bounds.y (), new_bounds.width (), new_bounds.height (),
4020
+ };
4021
+ GLboolean is_clipped = ca_layer_overlay->shared_state ->is_clipped ;
4022
+ GLfloat clip_rect[4 ] = {ca_layer_overlay->shared_state ->clip_rect .x (),
4023
+ ca_layer_overlay->shared_state ->clip_rect .y (),
4024
+ ca_layer_overlay->shared_state ->clip_rect .width (),
4025
+ ca_layer_overlay->shared_state ->clip_rect .height ()};
4026
+ GLint sorting_context_id = ca_layer_overlay->shared_state ->sorting_context_id ;
4027
+ SkMatrix44 transform = ca_layer_overlay->shared_state ->transform ;
4028
+ GLfloat gl_transform[16 ];
4029
+ transform.asColMajorf (gl_transform);
4030
+ unsigned filter = ca_layer_overlay->filter ;
4031
+
4032
+ gl_->ScheduleCALayerSharedStateCHROMIUM (
4033
+ ca_layer_overlay->shared_state ->opacity , is_clipped, clip_rect,
4034
+ sorting_context_id, gl_transform);
4035
+ gl_->ScheduleCALayerCHROMIUM (
4036
+ texture_id, contents_rect, ca_layer_overlay->background_color ,
4037
+ ca_layer_overlay->edge_aa_mask , bounds_rect, filter);
4038
+ }
4039
+
3857
4040
} // namespace cc
0 commit comments