Skip to content

Commit d9a09cd

Browse files
erikchenCommit bot
authored and
Commit bot
committed
Implement new RPDQ copy logic for CALayer promotion.
RPDQ promotion isn't enabled yet. That will be done in a follow up CL. The new logic heavily reuses the existing RPDQ drawing logic, but uses a custom drawing context instead of a DrawingFrame and RenderPass. BUG=581526 CQ_INCLUDE_TRYBOTS=master.tryserver.blink:linux_precise_blink_rel Review-Url: https://codereview.chromium.org/2205133003 Cr-Commit-Position: refs/heads/master@{#410767}
1 parent 84e985a commit d9a09cd

11 files changed

+263
-36
lines changed

cc/output/ca_layer_overlay.cc

+5-11
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ enum CALayerResult {
4444
CA_LAYER_FAILED_RENDER_PASS_BACKGROUND_FILTERS,
4545
CA_LAYER_FAILED_RENDER_PASS_MASK,
4646
CA_LAYER_FAILED_RENDER_PASS_FILTER_OPERATION,
47+
CA_LAYER_FAILED_RENDER_PASS_SORTING_CONTEXT_ID,
4748
CA_LAYER_FAILED_COUNT,
4849
};
4950

@@ -70,24 +71,17 @@ CALayerResult FromRenderPassQuad(ResourceProvider* resource_provider,
7071
CALayerOverlay* ca_layer_overlay) {
7172
if (quad->background_filters.size() != 0)
7273
return CA_LAYER_FAILED_RENDER_PASS_BACKGROUND_FILTERS;
73-
if (quad->mask_resource_id() != 0)
74-
return CA_LAYER_FAILED_RENDER_PASS_MASK;
74+
75+
if (quad->shared_quad_state->sorting_context_id != 0)
76+
return CA_LAYER_FAILED_RENDER_PASS_SORTING_CONTEXT_ID;
7577

7678
for (const FilterOperation& operation : quad->filters.operations()) {
7779
bool success = FilterOperationSupported(operation);
7880
if (!success)
7981
return CA_LAYER_FAILED_RENDER_PASS_FILTER_OPERATION;
8082
}
8183

82-
if (quad->filters_scale != gfx::Vector2dF(1, 1)) {
83-
for (const FilterOperation& operation : quad->filters.operations()) {
84-
if (operation.type() == FilterOperation::BLUR ||
85-
operation.type() == FilterOperation::DROP_SHADOW) {
86-
return CA_LAYER_FAILED_RENDER_PASS_FILTER_SCALE;
87-
}
88-
}
89-
}
90-
84+
ca_layer_overlay->rpdq = quad;
9185
ca_layer_overlay->contents_rect = gfx::RectF(0, 0, 1, 1);
9286

9387
// TODO(erikchen): Enable this when RenderPassDrawQuad promotion to CALayer

cc/output/ca_layer_overlay.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
namespace cc {
1616

1717
class DrawQuad;
18+
class RenderPassDrawQuad;
1819
class ResourceProvider;
1920

2021
// Holds information that is frequently shared between consecutive
@@ -23,7 +24,6 @@ class CC_EXPORT CALayerOverlaySharedState
2324
: public base::RefCounted<CALayerOverlaySharedState> {
2425
public:
2526
CALayerOverlaySharedState() {}
26-
2727
// Layers in a non-zero sorting context exist in the same 3D space and should
2828
// intersect.
2929
unsigned sorting_context_id = 0;
@@ -63,6 +63,9 @@ class CC_EXPORT CALayerOverlay {
6363
unsigned edge_aa_mask = 0;
6464
// The minification and magnification filters for the CALayer.
6565
unsigned filter;
66+
// If |rpdq| is present, then the renderer must draw the filter effects and
67+
// copy the result into an IOSurface.
68+
const RenderPassDrawQuad* rpdq = nullptr;
6669
};
6770

6871
typedef std::vector<CALayerOverlay> CALayerOverlayList;

cc/output/gl_renderer.cc

+195-12
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,11 @@ struct DrawRenderPassDrawQuadParams {
160160
const Resource* contents_texture = nullptr;
161161
const gfx::QuadF* clip_region = nullptr;
162162
bool flip_texture = false;
163-
164163
gfx::Transform window_matrix;
165164
gfx::Transform projection_matrix;
165+
gfx::Transform quad_to_target_transform;
166166

167-
// |frame| is needed for background effects.
167+
// |frame| is only used for background effects.
168168
DirectRenderer::DrawingFrame* frame = nullptr;
169169

170170
// Whether the texture to be sampled from needs to be flipped.
@@ -215,6 +215,7 @@ struct DrawRenderPassDrawQuadParams {
215215
bool use_color_matrix = false;
216216

217217
gfx::QuadF surface_quad;
218+
218219
gfx::Transform contents_device_transform;
219220
};
220221

@@ -1068,6 +1069,8 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
10681069

10691070
void GLRenderer::DrawRenderPassQuadInternal(
10701071
DrawRenderPassDrawQuadParams* params) {
1072+
params->quad_to_target_transform =
1073+
params->quad->shared_quad_state->quad_to_target_transform;
10711074
if (!InitializeRPDQParameters(params))
10721075
return;
10731076
UpdateRPDQShadersForBlending(params);
@@ -1093,8 +1096,7 @@ bool GLRenderer::InitializeRPDQParameters(
10931096
static_cast<float>(dst_rect.width()),
10941097
static_cast<float>(dst_rect.height()));
10951098
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,
10981100
params->dst_rect);
10991101
params->contents_device_transform =
11001102
params->window_matrix * params->projection_matrix * quad_rect_matrix;
@@ -1217,8 +1219,7 @@ bool GLRenderer::UpdateRPDQWithSkiaFilters(
12171219
if (clip_rect.IsEmpty()) {
12181220
clip_rect = current_draw_rect_;
12191221
}
1220-
gfx::Transform transform =
1221-
quad->shared_quad_state->quad_to_target_transform;
1222+
gfx::Transform transform = params->quad_to_target_transform;
12221223
gfx::QuadF clip_quad = gfx::QuadF(gfx::RectF(clip_rect));
12231224
gfx::QuadF local_clip = MapQuadToLocalSpace(transform, clip_quad);
12241225
params->dst_rect.Intersect(local_clip.BoundingBox());
@@ -1499,8 +1500,7 @@ void GLRenderer::UpdateRPDQUniforms(DrawRenderPassDrawQuadParams* params) {
14991500
}
15001501

15011502
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,
15041504
params.dst_rect, params.locations.matrix);
15051505

15061506
// Flush the compositor context before the filter bitmap goes out of
@@ -2728,6 +2728,8 @@ void GLRenderer::FinishDrawingQuadList() {
27282728
}
27292729

27302730
bool GLRenderer::FlippedFramebuffer(const DrawingFrame* frame) const {
2731+
if (force_drawing_frame_framebuffer_unflipped_)
2732+
return false;
27312733
if (frame->current_render_pass != frame->root_render_pass)
27322734
return true;
27332735
return FlippedRootFramebuffer();
@@ -3777,10 +3779,11 @@ void GLRenderer::ScheduleCALayers(DrawingFrame* frame) {
37773779
scoped_refptr<CALayerOverlaySharedState> shared_state;
37783780
size_t copied_render_pass_count = 0;
37793781
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;
37843787
}
37853788

37863789
ResourceId contents_resource_id = ca_layer_overlay.contents_resource_id;
@@ -3854,4 +3857,184 @@ void GLRenderer::ScheduleOverlays(DrawingFrame* frame) {
38543857
}
38553858
}
38563859

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(&params))
3907+
return;
3908+
3909+
if (!UpdateRPDQWithSkiaFilters(&params))
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(&params);
3974+
UpdateRPDQBlendMode(&params);
3975+
ChooseRPDQProgram(&params);
3976+
UpdateRPDQUniforms(&params);
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+
38574040
} // namespace cc

cc/output/gl_renderer.h

+24
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,22 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
270270
void ScheduleCALayers(DrawingFrame* frame);
271271
void ScheduleOverlays(DrawingFrame* frame);
272272

273+
// Copies the contents of the render pass draw quad, including filter effects,
274+
// to an overlay resource, returned in |resource|. The resource is allocated
275+
// from |overlay_resource_pool_|.
276+
// The resulting Resource may be larger than the original quad. The new size
277+
// and position is placed in |new_bounds|.
278+
void CopyRenderPassDrawQuadToOverlayResource(
279+
const CALayerOverlay* ca_layer_overlay,
280+
Resource** resource,
281+
DrawingFrame* frame,
282+
gfx::RectF* new_bounds);
283+
284+
// Schedules the |ca_layer_overlay|, which is guaranteed to have a non-null
285+
// |rpdq| parameter.
286+
void ScheduleRenderPassDrawQuad(const CALayerOverlay* ca_layer_overlay,
287+
DrawingFrame* external_frame);
288+
273289
using OverlayResourceLock =
274290
std::unique_ptr<ResourceProvider::ScopedReadLockGL>;
275291
using OverlayResourceLockList = std::vector<OverlayResourceLock>;
@@ -534,6 +550,14 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
534550

535551
// If true, draw a green border after compositing a texture quad using GL.
536552
bool gl_composited_texture_quad_border_;
553+
554+
// The method FlippedFramebuffer determines whether the framebuffer associated
555+
// with a DrawingFrame is flipped. It makes the assumption that the
556+
// DrawingFrame is being used as part of a render pass. If a DrawingFrame is
557+
// not being used as part of a render pass, setting it here forces
558+
// FlippedFramebuffer to return |true|.
559+
bool force_drawing_frame_framebuffer_unflipped_ = false;
560+
537561
BoundGeometry bound_geometry_;
538562
DISALLOW_COPY_AND_ASSIGN(GLRenderer);
539563
};

cc/output/overlay_processor.cc

-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ bool OverlayProcessor::ProcessForCALayers(
5252
// layers then clear the list and remove the backbuffer from the overcandidate
5353
// list.
5454
overlay_candidates->clear();
55-
render_pass->quad_list.clear();
5655
overlay_damage_rect_ = render_pass->output_rect;
5756
*damage_rect = gfx::Rect();
5857
return true;

0 commit comments

Comments
 (0)