1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/output/compositor_frame.h"
6 #include "cc/output/delegated_frame_data.h"
7 #include "cc/quads/render_pass.h"
8 #include "cc/quads/render_pass_id.h"
9 #include "cc/quads/solid_color_draw_quad.h"
10 #include "cc/quads/surface_draw_quad.h"
11 #include "cc/surfaces/surface.h"
12 #include "cc/surfaces/surface_factory.h"
13 #include "cc/surfaces/surface_factory_client.h"
14 #include "cc/surfaces/surface_hittest.h"
15 #include "cc/surfaces/surface_id_allocator.h"
16 #include "cc/surfaces/surface_manager.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "third_party/skia/include/core/SkColor.h"
19 #include "ui/gfx/geometry/size.h"
23 class EmptySurfaceFactoryClient
: public SurfaceFactoryClient
{
25 void ReturnResources(const ReturnedResourceArray
& resources
) override
{}
28 // This test verifies that hit testing on a surface that does not exist does
30 TEST(SurfaceHittestTest
, Hittest_BadCompositorFrameDoesNotCrash
) {
31 SurfaceManager manager
;
32 EmptySurfaceFactoryClient client
;
33 SurfaceFactory
factory(&manager
, &client
);
34 SurfaceIdAllocator
root_allocator(2);
36 SurfaceId root_surface_id
= root_allocator
.GenerateId();
37 SurfaceId child_surface_id
;
38 // Give the child surface an invalid ID.
39 child_surface_id
.id
= 0xdeadbeef;
41 gfx::Size
root_size(300, 300);
42 gfx::Rect
root_rect(root_size
);
43 gfx::Size
child_size(200, 200);
44 gfx::Rect
child_rect(child_size
);
45 gfx::Rect
child_solid_quad_size(100, 100);
46 gfx::Rect
child_solid_quad_rect(child_solid_quad_size
);
48 // Creates a root surface.
49 factory
.Create(root_surface_id
);
50 RenderPassId
root_id(1, 1);
51 scoped_ptr
<RenderPass
> root_pass
= RenderPass::Create();
52 root_pass
->SetNew(root_id
, root_rect
, root_rect
, gfx::Transform());
54 // Add a reference to the child surface on the root surface.
55 SharedQuadState
* root_shared_state
=
56 root_pass
->CreateAndAppendSharedQuadState();
57 root_shared_state
->SetAll(
58 gfx::Transform(1.0f
, 0.0f
, 0.0f
, 50.0f
, 0.0f
, 1.0f
, 0.0f
, 50.0f
, 0.0f
,
59 0.0f
, 1.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 1.0f
),
60 root_size
, root_rect
, root_rect
, false, 1.0f
, SkXfermode::kSrcOver_Mode
,
62 SurfaceDrawQuad
* surface_quad
=
63 root_pass
->CreateAndAppendDrawQuad
<SurfaceDrawQuad
>();
64 surface_quad
->SetNew(root_pass
->shared_quad_state_list
.back(), child_rect
,
65 child_rect
, child_surface_id
);
67 // Submit the root frame.
68 scoped_ptr
<DelegatedFrameData
> root_delegated_frame_data(
69 new DelegatedFrameData
);
70 root_delegated_frame_data
->render_pass_list
.push_back(root_pass
.Pass());
71 scoped_ptr
<CompositorFrame
> root_frame(new CompositorFrame
);
72 root_frame
->delegated_frame_data
= root_delegated_frame_data
.Pass();
73 factory
.SubmitCompositorFrame(root_surface_id
, root_frame
.Pass(),
74 SurfaceFactory::DrawCallback());
77 SurfaceHittest
hittest(&manager
);
78 gfx::Point transformed_point
;
79 EXPECT_EQ(root_surface_id
,
80 hittest
.Hittest(root_surface_id
, gfx::Point(100, 100),
84 factory
.Destroy(root_surface_id
);
87 TEST(SurfaceHittestTest
, Hittest_SingleSurface
) {
88 SurfaceManager manager
;
89 EmptySurfaceFactoryClient client
;
90 SurfaceFactory
factory(&manager
, &client
);
91 SurfaceIdAllocator
root_allocator(2);
93 // Creates a root surface.
94 SurfaceId root_surface_id
= root_allocator
.GenerateId();
95 factory
.Create(root_surface_id
);
96 gfx::Rect
rect(300, 300);
97 RenderPassId
id(1, 1);
98 scoped_ptr
<RenderPass
> pass
= RenderPass::Create();
99 pass
->SetNew(id
, rect
, rect
, gfx::Transform());
100 scoped_ptr
<DelegatedFrameData
> delegated_frame_data(new DelegatedFrameData
);
101 delegated_frame_data
->render_pass_list
.push_back(pass
.Pass());
102 scoped_ptr
<CompositorFrame
> root_frame(new CompositorFrame
);
103 root_frame
->delegated_frame_data
= delegated_frame_data
.Pass();
104 factory
.SubmitCompositorFrame(root_surface_id
, root_frame
.Pass(),
105 SurfaceFactory::DrawCallback());
108 SurfaceHittest
hittest(&manager
);
109 gfx::Point transformed_point
;
110 EXPECT_EQ(root_surface_id
,
111 hittest
.Hittest(root_surface_id
, gfx::Point(100, 100),
112 &transformed_point
));
113 EXPECT_EQ(gfx::Point(100, 100), transformed_point
);
116 factory
.Destroy(root_surface_id
);
119 TEST(SurfaceHittestTest
, Hittest_ChildSurface
) {
120 SurfaceManager manager
;
121 EmptySurfaceFactoryClient client
;
122 SurfaceFactory
factory(&manager
, &client
);
123 SurfaceIdAllocator
root_allocator(2);
124 SurfaceIdAllocator
child_allocator(3);
126 SurfaceId root_surface_id
= root_allocator
.GenerateId();
127 SurfaceId child_surface_id
= child_allocator
.GenerateId();
128 gfx::Size
root_size(300, 300);
129 gfx::Rect
root_rect(root_size
);
130 gfx::Size
child_size(200, 200);
131 gfx::Rect
child_rect(child_size
);
132 gfx::Rect
child_solid_quad_size(100, 100);
133 gfx::Rect
child_solid_quad_rect(child_solid_quad_size
);
135 // Creates a root surface.
136 factory
.Create(root_surface_id
);
137 RenderPassId
root_id(1, 1);
138 scoped_ptr
<RenderPass
> root_pass
= RenderPass::Create();
139 root_pass
->SetNew(root_id
, root_rect
, root_rect
, gfx::Transform());
141 // Add a reference to the child surface on the root surface.
142 SharedQuadState
* root_shared_state
=
143 root_pass
->CreateAndAppendSharedQuadState();
144 root_shared_state
->SetAll(gfx::Transform(1.0f
, 0.0f
, 0.0f
, 50.0f
,
145 0.0f
, 1.0f
, 0.0f
, 50.0f
,
146 0.0f
, 0.0f
, 1.0f
, 0.0f
,
147 0.0f
, 0.0f
, 0.0f
, 1.0f
),
148 root_size
, root_rect
, root_rect
, false, 1.0f
,
149 SkXfermode::kSrcOver_Mode
, 0);
150 SurfaceDrawQuad
* surface_quad
=
151 root_pass
->CreateAndAppendDrawQuad
<SurfaceDrawQuad
>();
152 surface_quad
->SetNew(root_pass
->shared_quad_state_list
.back(), child_rect
,
153 child_rect
, child_surface_id
);
155 // Submit the root frame.
156 scoped_ptr
<DelegatedFrameData
> root_delegated_frame_data(
157 new DelegatedFrameData
);
158 root_delegated_frame_data
->render_pass_list
.push_back(root_pass
.Pass());
159 scoped_ptr
<CompositorFrame
> root_frame(new CompositorFrame
);
160 root_frame
->delegated_frame_data
= root_delegated_frame_data
.Pass();
161 factory
.SubmitCompositorFrame(root_surface_id
, root_frame
.Pass(),
162 SurfaceFactory::DrawCallback());
164 // Creates a child surface.
165 factory
.Create(child_surface_id
);
166 RenderPassId
child_id(1, 1);
167 scoped_ptr
<RenderPass
> child_pass
= RenderPass::Create();
168 child_pass
->SetNew(child_id
, child_rect
, child_rect
, gfx::Transform());
170 // Add a solid quad in the child surface.
171 SharedQuadState
* child_shared_state
=
172 child_pass
->CreateAndAppendSharedQuadState();
173 child_shared_state
->SetAll(gfx::Transform(1.0f
, 0.0f
, 0.0f
, 50.0f
,
174 0.0f
, 1.0f
, 0.0f
, 50.0f
,
175 0.0f
, 0.0f
, 1.0f
, 0.0f
,
176 0.0f
, 0.0f
, 0.0f
, 1.0f
),
177 root_size
, root_rect
, root_rect
, false, 1.0f
,
178 SkXfermode::kSrcOver_Mode
, 0);
179 SolidColorDrawQuad
* color_quad
=
180 child_pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
181 color_quad
->SetNew(child_pass
->shared_quad_state_list
.back(),
182 child_solid_quad_rect
, child_solid_quad_rect
,
183 SK_ColorYELLOW
, false);
186 scoped_ptr
<DelegatedFrameData
> child_delegated_frame_data(
187 new DelegatedFrameData
);
188 child_delegated_frame_data
->render_pass_list
.push_back(child_pass
.Pass());
189 scoped_ptr
<CompositorFrame
> child_frame(new CompositorFrame
);
190 child_frame
->delegated_frame_data
= child_delegated_frame_data
.Pass();
191 factory
.SubmitCompositorFrame(child_surface_id
, child_frame
.Pass(),
192 SurfaceFactory::DrawCallback());
195 SurfaceHittest
hittest(&manager
);
196 gfx::Point transformed_point
;
197 EXPECT_EQ(root_surface_id
,
198 hittest
.Hittest(root_surface_id
, gfx::Point(10, 10),
199 &transformed_point
));
200 EXPECT_EQ(gfx::Point(10, 10), transformed_point
);
201 EXPECT_EQ(root_surface_id
,
202 hittest
.Hittest(root_surface_id
, gfx::Point(99, 99),
203 &transformed_point
));
204 EXPECT_EQ(gfx::Point(99, 99), transformed_point
);
205 EXPECT_EQ(child_surface_id
,
206 hittest
.Hittest(root_surface_id
, gfx::Point(100, 100),
207 &transformed_point
));
208 EXPECT_EQ(gfx::Point(50, 50), transformed_point
);
209 EXPECT_EQ(child_surface_id
,
210 hittest
.Hittest(root_surface_id
, gfx::Point(199, 199),
211 &transformed_point
));
212 EXPECT_EQ(gfx::Point(149, 149), transformed_point
);
213 EXPECT_EQ(root_surface_id
,
214 hittest
.Hittest(root_surface_id
, gfx::Point(200, 200),
215 &transformed_point
));
216 EXPECT_EQ(gfx::Point(200, 200), transformed_point
);
217 EXPECT_EQ(root_surface_id
,
218 hittest
.Hittest(root_surface_id
, gfx::Point(290, 290),
219 &transformed_point
));
220 EXPECT_EQ(gfx::Point(290, 290), transformed_point
);
223 factory
.Destroy(root_surface_id
);
224 factory
.Destroy(child_surface_id
);