summaryrefslogtreecommitdiffstats
path: root/cc/surfaces
diff options
context:
space:
mode:
authorfsamuel <fsamuel@chromium.org>2015-12-06 06:54:05 -0800
committerCommit bot <commit-bot@chromium.org>2015-12-06 14:55:08 +0000
commita40c9c16df5a0c9a9e14411dc3aa9a3dcde7e498 (patch)
treefca19c1e1f0b0c49f567c661ea35e7c4580f5a68 /cc/surfaces
parent79adad4e7973e44df1ee34b4952c2bfade88ee01 (diff)
downloadchromium_src-a40c9c16df5a0c9a9e14411dc3aa9a3dcde7e498.zip
chromium_src-a40c9c16df5a0c9a9e14411dc3aa9a3dcde7e498.tar.gz
chromium_src-a40c9c16df5a0c9a9e14411dc3aa9a3dcde7e498.tar.bz2
cc: Allow Surfaces clients to customize hit testing
Until we have a better hit testing data structure based on slimming paint work, Mus needs to annotate surfaces hit testing with additional information for shadows. This CL provides a generic customization hook to allow a Surfaces client to make a hit testing decision based on factors unknown to cc. Note that this is a short term solution until we have a better hit testing data structure from slimming paint. BUG=548424 CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel Review URL: https://codereview.chromium.org/1503553002 Cr-Commit-Position: refs/heads/master@{#363371}
Diffstat (limited to 'cc/surfaces')
-rw-r--r--cc/surfaces/BUILD.gn1
-rw-r--r--cc/surfaces/surface_hittest.cc12
-rw-r--r--cc/surfaces/surface_hittest.h5
-rw-r--r--cc/surfaces/surface_hittest_delegate.h24
-rw-r--r--cc/surfaces/surface_hittest_unittest.cc143
5 files changed, 173 insertions, 12 deletions
diff --git a/cc/surfaces/BUILD.gn b/cc/surfaces/BUILD.gn
index 6dd7240..cfb42b7 100644
--- a/cc/surfaces/BUILD.gn
+++ b/cc/surfaces/BUILD.gn
@@ -33,6 +33,7 @@ component("surfaces") {
"surface_factory_client.h",
"surface_hittest.cc",
"surface_hittest.h",
+ "surface_hittest_delegate.h",
"surface_id_allocator.cc",
"surface_id_allocator.h",
"surface_manager.cc",
diff --git a/cc/surfaces/surface_hittest.cc b/cc/surfaces/surface_hittest.cc
index b7414de..1f443d6 100644
--- a/cc/surfaces/surface_hittest.cc
+++ b/cc/surfaces/surface_hittest.cc
@@ -10,15 +10,16 @@
#include "cc/quads/render_pass_draw_quad.h"
#include "cc/quads/surface_draw_quad.h"
#include "cc/surfaces/surface.h"
+#include "cc/surfaces/surface_hittest_delegate.h"
#include "cc/surfaces/surface_manager.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/transform.h"
namespace cc {
-namespace {
-}
-SurfaceHittest::SurfaceHittest(SurfaceManager* manager) : manager_(manager) {}
+SurfaceHittest::SurfaceHittest(SurfaceHittestDelegate* delegate,
+ SurfaceManager* manager)
+ : delegate_(delegate), manager_(manager) {}
SurfaceHittest::~SurfaceHittest() {}
@@ -95,6 +96,11 @@ bool SurfaceHittest::GetTargetSurfaceAtPointInternal(
// Surface.
const SurfaceDrawQuad* surface_quad = SurfaceDrawQuad::MaterialCast(quad);
+ if (delegate_ &&
+ delegate_->RejectHitTarget(surface_quad, point_in_quad_space)) {
+ continue;
+ }
+
gfx::Transform transform_to_child_space;
if (GetTargetSurfaceAtPointInternal(
surface_quad->surface_id, RenderPassId(), point_in_quad_space,
diff --git a/cc/surfaces/surface_hittest.h b/cc/surfaces/surface_hittest.h
index 60fa893..ce45a90 100644
--- a/cc/surfaces/surface_hittest.h
+++ b/cc/surfaces/surface_hittest.h
@@ -16,16 +16,18 @@ class Transform;
}
namespace cc {
+
class DrawQuad;
class QuadList;
class RenderPass;
class RenderPassId;
+class SurfaceHittestDelegate;
class SurfaceManager;
// Performs a hittest in surface quads.
class CC_SURFACES_EXPORT SurfaceHittest {
public:
- explicit SurfaceHittest(SurfaceManager* manager);
+ SurfaceHittest(SurfaceHittestDelegate* delegate, SurfaceManager* manager);
~SurfaceHittest();
// Returns the target surface that falls underneath the provided |point|.
@@ -67,6 +69,7 @@ class CC_SURFACES_EXPORT SurfaceHittest {
gfx::Transform* target_to_quad_transform,
gfx::Point* point_in_quad_space);
+ SurfaceHittestDelegate* const delegate_;
SurfaceManager* const manager_;
};
} // namespace cc
diff --git a/cc/surfaces/surface_hittest_delegate.h b/cc/surfaces/surface_hittest_delegate.h
new file mode 100644
index 0000000..1f0fbf9
--- /dev/null
+++ b/cc/surfaces/surface_hittest_delegate.h
@@ -0,0 +1,24 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_SURFACES_SURFACE_HITTEST_DELEGATE_H_
+#define CC_SURFACES_SURFACE_HITTEST_DELEGATE_H_
+
+namespace cc {
+
+class SurfaceDrawQuad;
+
+// Clients of SurfaceHittest can provide a SurfaceHittestDelegate implementation
+// to override the hit target based on metadata outside of the Surfaces system.
+class SurfaceHittestDelegate {
+ public:
+ // Return true if this delegate rejects this |surface_quad| as a candidate hit
+ // target.
+ virtual bool RejectHitTarget(const SurfaceDrawQuad* surface_quad,
+ const gfx::Point& point_in_quad_space) = 0;
+};
+
+} // namespace cc
+
+#endif // CC_SURFACES_SURFACE_HITTEST_DELEGATE_H_
diff --git a/cc/surfaces/surface_hittest_unittest.cc b/cc/surfaces/surface_hittest_unittest.cc
index 2b59f0a..144d0d6 100644
--- a/cc/surfaces/surface_hittest_unittest.cc
+++ b/cc/surfaces/surface_hittest_unittest.cc
@@ -25,8 +25,11 @@ struct TestCase {
gfx::Point expected_output_point;
};
-void RunTests(SurfaceManager* manager, TestCase* tests, size_t test_count) {
- SurfaceHittest hittest(manager);
+void RunTests(SurfaceHittestDelegate* delegate,
+ SurfaceManager* manager,
+ TestCase* tests,
+ size_t test_count) {
+ SurfaceHittest hittest(delegate, manager);
for (size_t i = 0; i < test_count; ++i) {
const TestCase& test = tests[i];
gfx::Point point(test.input_point);
@@ -83,7 +86,7 @@ TEST(SurfaceHittestTest, Hittest_BadCompositorFrameDoesNotCrash) {
SurfaceFactory::DrawCallback());
{
- SurfaceHittest hittest(&manager);
+ SurfaceHittest hittest(nullptr, &manager);
// It is expected this test will complete without crashes.
gfx::Transform transform;
EXPECT_EQ(root_surface_id,
@@ -120,7 +123,7 @@ TEST(SurfaceHittestTest, Hittest_SingleSurface) {
},
};
- RunTests(&manager, tests, arraysize(tests));
+ RunTests(nullptr, &manager, tests, arraysize(tests));
factory.Destroy(root_surface_id);
}
@@ -215,7 +218,7 @@ TEST(SurfaceHittestTest, Hittest_ChildSurface) {
}
};
- RunTests(&manager, tests, arraysize(tests));
+ RunTests(nullptr, &manager, tests, arraysize(tests));
// Submit another root frame, with a slightly perturbed child Surface.
root_frame = CreateCompositorFrame(root_rect, &root_pass);
@@ -233,7 +236,7 @@ TEST(SurfaceHittestTest, Hittest_ChildSurface) {
// Verify that point (100, 100) no longer falls on the child surface.
// Verify that the transform to the child surface's space has also shifted.
{
- SurfaceHittest hittest(&manager);
+ SurfaceHittest hittest(nullptr, &manager);
gfx::Point point(100, 100);
gfx::Transform transform;
@@ -355,7 +358,7 @@ TEST(SurfaceHittestTest, Hittest_InvalidRenderPassDrawQuad) {
}
};
- RunTests(&manager, tests, arraysize(tests));
+ RunTests(nullptr, &manager, tests, arraysize(tests));
factory.Destroy(root_surface_id);
factory.Destroy(child_surface_id);
@@ -459,7 +462,131 @@ TEST(SurfaceHittestTest, Hittest_RenderPassDrawQuad) {
}
};
- RunTests(&manager, tests, arraysize(tests));
+ RunTests(nullptr, &manager, tests, arraysize(tests));
+
+ factory.Destroy(root_surface_id);
+}
+
+TEST(SurfaceHittestTest, Hittest_SingleSurface_WithInsetsDelegate) {
+ SurfaceManager manager;
+ EmptySurfaceFactoryClient client;
+ SurfaceFactory factory(&manager, &client);
+
+ // Creates a root surface.
+ gfx::Rect root_rect(300, 300);
+ RenderPass* root_pass = nullptr;
+ scoped_ptr<CompositorFrame> root_frame =
+ CreateCompositorFrame(root_rect, &root_pass);
+
+ // Add a reference to the child surface on the root surface.
+ SurfaceIdAllocator child_allocator(3);
+ SurfaceId child_surface_id = child_allocator.GenerateId();
+ gfx::Rect child_rect(200, 200);
+ CreateSurfaceDrawQuad(
+ root_pass,
+ gfx::Transform(1.0f, 0.0f, 0.0f, 50.0f,
+ 0.0f, 1.0f, 0.0f, 50.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f),
+ root_rect, child_rect, child_surface_id);
+
+ // Submit the root frame.
+ SurfaceIdAllocator root_allocator(2);
+ SurfaceId root_surface_id = root_allocator.GenerateId();
+ factory.Create(root_surface_id);
+ factory.SubmitCompositorFrame(root_surface_id, std::move(root_frame),
+ SurfaceFactory::DrawCallback());
+
+ // Creates a child surface.
+ RenderPass* child_pass = nullptr;
+ scoped_ptr<CompositorFrame> child_frame =
+ CreateCompositorFrame(child_rect, &child_pass);
+
+ // Add a solid quad in the child surface.
+ gfx::Rect child_solid_quad_rect(200, 200);
+ CreateSolidColorDrawQuad(
+ child_pass,
+ gfx::Transform(),
+ root_rect, child_solid_quad_rect);
+
+ // Submit the frame.
+ factory.Create(child_surface_id);
+ factory.SubmitCompositorFrame(child_surface_id, std::move(child_frame),
+ SurfaceFactory::DrawCallback());
+
+ TestCase test_expectations_without_insets[] = {
+ {
+ root_surface_id,
+ gfx::Point(50, 50),
+ child_surface_id,
+ gfx::Point(0, 0)
+ },
+ {
+ root_surface_id,
+ gfx::Point(60, 60),
+ child_surface_id,
+ gfx::Point(10, 10)
+ },
+ {
+ root_surface_id,
+ gfx::Point(239, 239),
+ child_surface_id,
+ gfx::Point(189, 189)
+ },
+ {
+ root_surface_id,
+ gfx::Point(249, 249),
+ child_surface_id,
+ gfx::Point(199, 199)
+ },
+ };
+
+ TestSurfaceHittestDelegate delegate;
+ RunTests(&delegate, &manager, test_expectations_without_insets,
+ arraysize(test_expectations_without_insets));
+
+ // Verify that insets have NOT affected hit targeting.
+ EXPECT_EQ(0, delegate.target_overrides());
+
+ delegate.AddInsetsForSurface(child_surface_id, gfx::Insets(10, 10, 10, 10));
+
+ TestCase test_expectations_with_insets[] = {
+ // Point (50, 50) falls outside the child surface due to the insets
+ // introduced above.
+ {
+ root_surface_id,
+ gfx::Point(50, 50),
+ root_surface_id,
+ gfx::Point(50, 50)
+ },
+ // These two points still fall within the child surface.
+ {
+ root_surface_id,
+ gfx::Point(60, 60),
+ child_surface_id,
+ gfx::Point(10, 10)
+ },
+ {
+ root_surface_id,
+ gfx::Point(239, 239),
+ child_surface_id,
+ gfx::Point(189, 189)
+ },
+ // Point (249, 249) falls outside the child surface due to the insets
+ // introduced above.
+ {
+ root_surface_id,
+ gfx::Point(249, 249),
+ root_surface_id,
+ gfx::Point(249, 249)
+ },
+ };
+
+ RunTests(&delegate, &manager, test_expectations_with_insets,
+ arraysize(test_expectations_with_insets));
+
+ // Verify that insets have affected hit targeting.
+ EXPECT_EQ(2, delegate.target_overrides());
factory.Destroy(root_surface_id);
}