summaryrefslogtreecommitdiffstats
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
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}
-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
-rw-r--r--cc/test/surface_hittest_test_helpers.cc27
-rw-r--r--cc/test/surface_hittest_test_helpers.h26
-rw-r--r--components/mus/surfaces/surfaces_state.cc4
-rw-r--r--content/browser/compositor/delegated_frame_host.cc4
9 files changed, 229 insertions, 17 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);
}
diff --git a/cc/test/surface_hittest_test_helpers.cc b/cc/test/surface_hittest_test_helpers.cc
index 8c57959..b83d6d4 100644
--- a/cc/test/surface_hittest_test_helpers.cc
+++ b/cc/test/surface_hittest_test_helpers.cc
@@ -92,5 +92,32 @@ scoped_ptr<CompositorFrame> CreateCompositorFrame(const gfx::Rect& root_rect,
return root_frame;
}
+TestSurfaceHittestDelegate::TestSurfaceHittestDelegate()
+ : target_overrides_(0) {}
+
+TestSurfaceHittestDelegate::~TestSurfaceHittestDelegate() {}
+
+void TestSurfaceHittestDelegate::AddInsetsForSurface(
+ const SurfaceId& surface_id,
+ const gfx::Insets& inset) {
+ insets_for_surface_.insert(std::make_pair(surface_id, inset));
+}
+
+bool TestSurfaceHittestDelegate::RejectHitTarget(
+ const SurfaceDrawQuad* surface_quad,
+ const gfx::Point& point_in_quad_space) {
+ if (!insets_for_surface_.count(surface_quad->surface_id))
+ return false;
+ gfx::Rect bounds(surface_quad->rect);
+ bounds.Inset(insets_for_surface_[surface_quad->surface_id]);
+ // If the point provided falls outside the inset, then we skip this surface.
+ if (!bounds.Contains(point_in_quad_space)) {
+ if (surface_quad->rect.Contains(point_in_quad_space))
+ ++target_overrides_;
+ return true;
+ }
+ return false;
+}
+
} // namespace test
} // namespace cc
diff --git a/cc/test/surface_hittest_test_helpers.h b/cc/test/surface_hittest_test_helpers.h
index be4ad2e..4a27659 100644
--- a/cc/test/surface_hittest_test_helpers.h
+++ b/cc/test/surface_hittest_test_helpers.h
@@ -5,9 +5,14 @@
#ifndef CC_TEST_SURFACE_HITTEST_TEST_HELPERS_H_
#define CC_TEST_SURFACE_HITTEST_TEST_HELPERS_H_
+#include <map>
+
+#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "cc/quads/render_pass.h"
#include "cc/surfaces/surface_factory_client.h"
+#include "cc/surfaces/surface_hittest_delegate.h"
+#include "ui/gfx/geometry/insets.h"
namespace gfx {
class Transform;
@@ -60,6 +65,27 @@ scoped_ptr<CompositorFrame> CreateCompositorFrameWithRenderPassList(
scoped_ptr<CompositorFrame> CreateCompositorFrame(const gfx::Rect& root_rect,
RenderPass** render_pass);
+class TestSurfaceHittestDelegate : public SurfaceHittestDelegate {
+ public:
+ TestSurfaceHittestDelegate();
+ ~TestSurfaceHittestDelegate();
+
+ int target_overrides() const { return target_overrides_; }
+
+ void AddInsetsForSurface(const SurfaceId& surface_id,
+ const gfx::Insets& inset);
+
+ // SurfaceHittestDelegate implementation.
+ bool RejectHitTarget(const SurfaceDrawQuad* surface_quad,
+ const gfx::Point& point_in_quad_space) override;
+
+ private:
+ int target_overrides_;
+ std::map<SurfaceId, gfx::Insets> insets_for_surface_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestSurfaceHittestDelegate);
+};
+
} // namespace test
} // namespace cc
diff --git a/components/mus/surfaces/surfaces_state.cc b/components/mus/surfaces/surfaces_state.cc
index ea203ba..51b7358 100644
--- a/components/mus/surfaces/surfaces_state.cc
+++ b/components/mus/surfaces/surfaces_state.cc
@@ -7,9 +7,7 @@
namespace mus {
SurfacesState::SurfacesState()
- : next_id_namespace_(1u),
- hit_tester_(&manager_) {
-}
+ : next_id_namespace_(1u), hit_tester_(nullptr, &manager_) {}
SurfacesState::~SurfacesState() {}
diff --git a/content/browser/compositor/delegated_frame_host.cc b/content/browser/compositor/delegated_frame_host.cc
index 2650a76..bf39969 100644
--- a/content/browser/compositor/delegated_frame_host.cc
+++ b/content/browser/compositor/delegated_frame_host.cc
@@ -211,7 +211,7 @@ cc::SurfaceId DelegatedFrameHost::SurfaceIdAtPoint(
gfx::Point* transformed_point) {
if (surface_id_.is_null())
return surface_id_;
- cc::SurfaceHittest hittest(GetSurfaceManager());
+ cc::SurfaceHittest hittest(nullptr, GetSurfaceManager());
gfx::Transform target_transform;
cc::SurfaceId target_surface_id =
hittest.GetTargetSurfaceAtPoint(surface_id_, point, &target_transform);
@@ -230,7 +230,7 @@ void DelegatedFrameHost::TransformPointToLocalCoordSpace(
return;
gfx::Transform transform;
- cc::SurfaceHittest hittest(GetSurfaceManager());
+ cc::SurfaceHittest hittest(nullptr, GetSurfaceManager());
if (hittest.GetTransformToTargetSurface(surface_id_, original_surface,
&transform) &&
transform.GetInverse(&transform)) {