Implement RenderPassDrawQuad fuzzing.
This CL introduces RenderPassDrawQuads to the fuzzable quad types. It
does not yet fuzz masks/filters.
R=kylechar@chromium.org, riajiang@chromium.org
Bug: 923088
Change-Id: Ia3c8331c3c8093aff5842d4d23ad6338c1a8897c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1566363
Commit-Queue: Céline O'Neil <celineo@google.com>
Reviewed-by: kylechar <kylechar@chromium.org>
Reviewed-by: Ria Jiang <riajiang@chromium.org>
Auto-Submit: Céline O'Neil <celineo@google.com>
Cr-Commit-Position: refs/heads/master@{#654133}
diff --git a/components/viz/service/compositor_frame_fuzzer/BUILD.gn b/components/viz/service/compositor_frame_fuzzer/BUILD.gn
index 4530798..12ea598 100644
--- a/components/viz/service/compositor_frame_fuzzer/BUILD.gn
+++ b/components/viz/service/compositor_frame_fuzzer/BUILD.gn
@@ -29,6 +29,8 @@
sources = [
"$input_dir/1_quad_renderpass.asciipb",
"$input_dir/2_quad_renderpass.asciipb",
+ "$input_dir/nested_render_pass_draw_quads.asciipb",
+ "$input_dir/overlapping_quads_in_render_pass_draw_quad.asciipb",
"$input_dir/solid_color_tiled_background_with_2_quads_on_top.asciipb",
]
outputs = [
@@ -68,6 +70,7 @@
deps = [
":compositor_frame_fuzzer_proto",
+ ":generate_seed_corpus",
"//components/viz/service",
"//components/viz/test:test_support",
"//mojo/core/embedder",
diff --git a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.proto b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.proto
index b0153d5..9b9c1f9 100644
--- a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.proto
+++ b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.proto
@@ -15,7 +15,8 @@
message DrawQuad {
// If not present, defaults to same dimensions as quad, with identity
- // transform
+ // transform (or with |transform_to_root_target| if quad is a
+ // RenderPassDrawQuad).
optional SharedQuadState sqs = 1;
required Rect rect = 2;
@@ -26,6 +27,7 @@
oneof quad {
SolidColorDrawQuad solid_color_quad = 4;
TileDrawQuad tile_quad = 5;
+ RenderPassDrawQuad render_pass_quad = 6;
}
}
@@ -70,6 +72,13 @@
required bool force_anti_aliasing_off = 8;
}
+message RenderPassDrawQuad {
+ required RenderPass render_pass = 1;
+
+ // If not present, defaults to DrawQuad's |rect|
+ optional Rect tex_coord_rect = 2;
+}
+
// Spec to initialize a gfx::Rect.
// Defaults to the size of the renderer frame as defined in
// fuzzer_browser_process.cc, in the hopes that this generally yields more
diff --git a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc
index 6f3587a..e991f18 100644
--- a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc
+++ b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc
@@ -8,6 +8,8 @@
#include <utility>
#include "base/logging.h"
+#include "cc/base/math_util.h"
+#include "components/viz/common/quads/render_pass_draw_quad.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/tile_draw_quad.h"
#include "components/viz/common/resources/resource_sizes.h"
@@ -121,7 +123,7 @@
return std::move(data_);
}
-void FuzzedCompositorFrameBuilder::AddRenderPass(
+RenderPassId FuzzedCompositorFrameBuilder::AddRenderPass(
const content::fuzzing::proto::RenderPass& render_pass_spec) {
std::unique_ptr<RenderPass> pass = RenderPass::Create();
gfx::Rect rp_output_rect =
@@ -141,7 +143,8 @@
? GetTransformFromProtobuf(
render_pass_spec.transform_to_root_target())
: gfx::Transform();
- pass->SetNew(1, rp_output_rect, rp_damage_rect, transform_to_root_target);
+ pass->SetNew(next_pass_id_++, rp_output_rect, rp_damage_rect,
+ transform_to_root_target);
for (const content::fuzzing::proto::DrawQuad& quad_spec :
render_pass_spec.quad_list()) {
@@ -169,12 +172,18 @@
TryAddTileDrawQuad(pass.get(), quad_rect, quad_visible_rect, quad_spec);
break;
}
+ case content::fuzzing::proto::DrawQuad::kRenderPassQuad: {
+ TryAddRenderPassDrawQuad(pass.get(), quad_rect, quad_visible_rect,
+ quad_spec);
+ break;
+ }
case content::fuzzing::proto::DrawQuad::QUAD_NOT_SET: {
NOTREACHED();
}
}
}
data_.frame.render_pass_list.push_back(std::move(pass));
+ return data_.frame.render_pass_list.back()->id;
}
void FuzzedCompositorFrameBuilder::AddSolidColorDrawQuad(
@@ -228,6 +237,64 @@
data_.frame.resource_list.push_back(transferable_resource);
}
+void FuzzedCompositorFrameBuilder::TryAddRenderPassDrawQuad(
+ RenderPass* pass,
+ const gfx::Rect& rect,
+ const gfx::Rect& visible_rect,
+ const content::fuzzing::proto::DrawQuad& quad_spec) {
+ // Since child RenderPasses are allocated as textures, skip
+ // RenderPasses that would overflow our limit on allocated memory for
+ // this CompositorFrame.
+ gfx::Size render_pass_size =
+ GetRectFromProtobuf(
+ quad_spec.render_pass_quad().render_pass().output_rect())
+ .size();
+
+ // RenderPass texture dimensions are rounded up to a
+ // multiple of 64 pixels to reduce fragmentation.
+ constexpr int multiple = 64;
+ if (!cc::MathUtil::VerifyRoundup(render_pass_size.width(), multiple) ||
+ !cc::MathUtil::VerifyRoundup(render_pass_size.height(), multiple)) {
+ VLOG(1) << "Skipping RenderPassDrawQuad: bitmap of size "
+ << render_pass_size.ToString() << " can't be allocated.";
+ return;
+ }
+ render_pass_size = gfx::Size(
+ cc::MathUtil::UncheckedRoundUp(render_pass_size.width(), multiple),
+ cc::MathUtil::UncheckedRoundUp(render_pass_size.height(), multiple));
+
+ if (!TryReserveBitmapBytes(render_pass_size)) {
+ VLOG(1) << "Skipping RenderPassDrawQuad: bitmap of size "
+ << render_pass_size.ToString() << " can't be allocated.";
+ return;
+ }
+
+ // Build the child RenderPass and add it to the frame's
+ // RenderPassList.
+ RenderPassId child_pass_id =
+ AddRenderPass(quad_spec.render_pass_quad().render_pass());
+
+ // Unless a tex_coord_rect is defined in the protobuf specification,
+ // a good default is a rectangle covering the entire quad.
+ gfx::RectF tex_coord_rect = gfx::RectF(
+ quad_spec.render_pass_quad().has_tex_coord_rect()
+ ? GetRectFromProtobuf(quad_spec.render_pass_quad().tex_coord_rect())
+ : rect);
+
+ auto* shared_quad_state = pass->CreateAndAppendSharedQuadState();
+ ConfigureSharedQuadState(shared_quad_state, quad_spec);
+ auto* quad = pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
+ quad->SetNew(shared_quad_state, rect, visible_rect, child_pass_id,
+ /*mask_resource_id=*/ResourceId(),
+ /*mask_uv_rect=*/gfx::RectF(),
+ /*mask_texture_size=*/gfx::Size(),
+ /*filters_scale=*/gfx::Vector2dF(),
+ /*filters_origin=*/gfx::PointF(),
+ /*tex_coord_rect=*/tex_coord_rect,
+ /*force_anti_aliasing_off=*/false,
+ /*backdrop_filter_quality=*/1.0);
+}
+
void FuzzedCompositorFrameBuilder::ConfigureSharedQuadState(
SharedQuadState* shared_quad_state,
const content::fuzzing::proto::DrawQuad& quad_spec) {
@@ -241,12 +308,24 @@
Normalize(quad_spec.sqs().opacity()), SkBlendMode::kSrcOver,
quad_spec.sqs().sorting_context_id());
} else {
- shared_quad_state->SetAll(
- gfx::Transform(), GetRectFromProtobuf(quad_spec.rect()),
- GetRectFromProtobuf(quad_spec.visible_rect()), gfx::RRectF(),
- gfx::Rect(), /*is_clipped=*/false,
- /*are_contents_opaque=*/true, /*opacity=*/1.0, SkBlendMode::kSrcOver,
- /*sorting_context_id=*/0);
+ gfx::Transform transform;
+
+ if (quad_spec.quad_case() ==
+ content::fuzzing::proto::DrawQuad::kRenderPassQuad &&
+ quad_spec.render_pass_quad()
+ .render_pass()
+ .has_transform_to_root_target()) {
+ transform = GetTransformFromProtobuf(quad_spec.render_pass_quad()
+ .render_pass()
+ .transform_to_root_target());
+ }
+
+ shared_quad_state->SetAll(transform, GetRectFromProtobuf(quad_spec.rect()),
+ GetRectFromProtobuf(quad_spec.visible_rect()),
+ gfx::RRectF(), gfx::Rect(), /*is_clipped=*/false,
+ /*are_contents_opaque=*/true, /*opacity=*/1.0,
+ SkBlendMode::kSrcOver,
+ /*sorting_context_id=*/0);
}
}
diff --git a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.h b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.h
index da318c9..89a16ec 100644
--- a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.h
+++ b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.h
@@ -67,7 +67,7 @@
// reduce this if bots are running out of memory.
static constexpr uint64_t kMaxTextureMemory = 1 << 29;
- void AddRenderPass(
+ RenderPassId AddRenderPass(
const content::fuzzing::proto::RenderPass& render_pass_spec);
// Helper methods for AddRenderPass. Try* methods may return before
@@ -81,6 +81,11 @@
const gfx::Rect& rect,
const gfx::Rect& visible_rect,
const content::fuzzing::proto::DrawQuad& quad_spec);
+ void TryAddRenderPassDrawQuad(
+ RenderPass* pass,
+ const gfx::Rect& rect,
+ const gfx::Rect& visible_rect,
+ const content::fuzzing::proto::DrawQuad& quad_spec);
// Configure the SharedQuadState to match the specifications in the
// protobuf, if they are defined for this quad. Otherwise, use sensible
@@ -106,6 +111,8 @@
// specific bitmaps/textures.
uint64_t reserved_bytes_ = 0;
+ RenderPassId next_pass_id_ = 1;
+
// Frame and data being built.
FuzzedData data_;
diff --git a/components/viz/service/compositor_frame_fuzzer/text_format_seed_corpus/nested_render_pass_draw_quads.asciipb b/components/viz/service/compositor_frame_fuzzer/text_format_seed_corpus/nested_render_pass_draw_quads.asciipb
new file mode 100644
index 0000000..e028dda
--- /dev/null
+++ b/components/viz/service/compositor_frame_fuzzer/text_format_seed_corpus/nested_render_pass_draw_quads.asciipb
@@ -0,0 +1,171 @@
+output_rect: {
+ x: 0
+ y: 0
+ width: 620
+ height: 400
+}
+damage_rect: {
+ x: 0
+ y: 0
+ width: 620
+ height: 400
+}
+quad_list: [
+ {
+ rect: {
+ x: 0
+ y: 0
+ width: 200
+ height: 200
+ }
+ visible_rect: {
+ x: 0
+ y: 0
+ width: 200
+ height: 200
+ }
+ render_pass_quad: {
+ render_pass: {
+ output_rect: {
+ x: 0
+ y: 0
+ width: 200
+ height: 200
+ }
+ damage_rect: {
+ x: 0
+ y: 0
+ width: 200
+ height: 200
+ }
+ quad_list: [
+ {
+ rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ visible_rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ render_pass_quad: {
+ render_pass: {
+ output_rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ damage_rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ quad_list: [
+ {
+ rect: {
+ x: 0
+ y: 0
+ width: 300
+ height: 300
+ }
+ visible_rect: {
+ x: 0
+ y: 0
+ width: 300
+ height: 300
+ }
+ solid_color_quad: {
+ color: 0xFF0070FF
+ force_anti_aliasing_off: false
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ visible_rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ render_pass_quad: {
+ render_pass: {
+ transform_to_root_target : {
+ rotate: 0
+ scale_x: 1
+ scale_y: 1
+ translate_x: 100
+ translate_y: 100
+ }
+ output_rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ damage_rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ quad_list: [
+ {
+ rect: {
+ x: 0
+ y: 0
+ width: 300
+ height: 300
+ }
+ visible_rect: {
+ x: 0
+ y: 0
+ width: 300
+ height: 300
+ }
+ solid_color_quad: {
+ color: 0xFF9970FF
+ force_anti_aliasing_off: false
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ rect: {
+ x: 0
+ y: 0
+ width: 300
+ height: 300
+ }
+ visible_rect: {
+ x: 0
+ y: 0
+ width: 300
+ height: 300
+ }
+ solid_color_quad: {
+ color: 0xFFFF0070
+ force_anti_aliasing_off: false
+ }
+ }
+ ]
+ }
+ }
+ }
+]
diff --git a/components/viz/service/compositor_frame_fuzzer/text_format_seed_corpus/overlapping_quads_in_render_pass_draw_quad.asciipb b/components/viz/service/compositor_frame_fuzzer/text_format_seed_corpus/overlapping_quads_in_render_pass_draw_quad.asciipb
new file mode 100644
index 0000000..96dc650
--- /dev/null
+++ b/components/viz/service/compositor_frame_fuzzer/text_format_seed_corpus/overlapping_quads_in_render_pass_draw_quad.asciipb
@@ -0,0 +1,249 @@
+output_rect: {
+ x: 0
+ y: 0
+ width: 620
+ height: 400
+}
+damage_rect: {
+ x: 0
+ y: 0
+ width: 620
+ height: 400
+}
+quad_list: [
+ {
+ rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ visible_rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ solid_color_quad: {
+ color: 0xFFFF0070
+ force_anti_aliasing_off: false
+ }
+ sqs: {
+ transform: {
+ rotate: -10
+ scale_x: 1
+ scale_y: 1
+ translate_x: 50
+ translate_y: 50
+ }
+ layer_rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ visible_rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ clip_rect: {
+ x: 0
+ y: 0
+ width: 0
+ height: 0
+ }
+ is_clipped: false
+ are_contents_opaque: false
+ opacity: 0xFFFFFFFF
+ sorting_context_id: 0
+ }
+ },
+ {
+ rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ visible_rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ solid_color_quad: {
+ color: 0xFF70FF00
+ force_anti_aliasing_off: false
+ }
+ sqs: {
+ transform: {
+ rotate: 0
+ scale_x: 1
+ scale_y: 1
+ translate_x: 100
+ translate_y: 50
+ }
+ layer_rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ visible_rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ clip_rect: {
+ x: 0
+ y: 0
+ width: 0
+ height: 0
+ }
+ is_clipped: false
+ are_contents_opaque: true
+ opacity: 0xFFFFFFFF
+ sorting_context_id: 0
+ }
+ },
+ {
+ rect: {
+ x: 0
+ y: 0
+ width: 200
+ height: 200
+ }
+ visible_rect: {
+ x: 0
+ y: 0
+ width: 200
+ height: 200
+ }
+ render_pass_quad: {
+ render_pass: {
+ transform_to_root_target : {
+ rotate: 15
+ scale_x: 1
+ scale_y: 1
+ translate_x: 300
+ translate_y: 0
+ }
+ output_rect: {
+ x: 0
+ y: 0
+ width: 200
+ height: 200
+ }
+ damage_rect: {
+ x: 0
+ y: 0
+ width: 200
+ height: 200
+ }
+ quad_list: [
+ {
+ rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ visible_rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ solid_color_quad: {
+ color: 0xFF0070FF
+ force_anti_aliasing_off: false
+ }
+ sqs: {
+ transform: {
+ rotate: -10
+ scale_x: 1
+ scale_y: 1
+ translate_x: 50
+ translate_y: 50
+ }
+ layer_rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ visible_rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ clip_rect: {
+ x: 0
+ y: 0
+ width: 0
+ height: 0
+ }
+ is_clipped: false
+ are_contents_opaque: true
+ opacity: 0xFFFFFFFF
+ sorting_context_id: 0
+ }
+ },
+ {
+ rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ visible_rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ solid_color_quad: {
+ color: 0xFF9970FF
+ force_anti_aliasing_off: false
+ }
+ sqs: {
+ transform: {
+ rotate: 0
+ scale_x: 1
+ scale_y: 1
+ translate_x: 100
+ translate_y: 50
+ }
+ layer_rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ visible_rect: {
+ x: 0
+ y: 0
+ width: 100
+ height: 100
+ }
+ clip_rect: {
+ x: 0
+ y: 0
+ width: 0
+ height: 0
+ }
+ is_clipped: false
+ are_contents_opaque: true
+ opacity: 0xFFFFFFFF
+ sorting_context_id: 0
+ }
+ }
+ ]
+ }
+ }
+ }
+]