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_draw_quad.h"
9 #include "cc/quads/render_pass_id.h"
10 #include "cc/quads/solid_color_draw_quad.h"
11 #include "cc/quads/surface_draw_quad.h"
12 #include "cc/surfaces/surface.h"
13 #include "cc/surfaces/surface_factory.h"
14 #include "cc/surfaces/surface_factory_client.h"
15 #include "cc/surfaces/surface_hittest.h"
16 #include "cc/surfaces/surface_id_allocator.h"
17 #include "cc/surfaces/surface_manager.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "third_party/skia/include/core/SkColor.h"
20 #include "ui/gfx/geometry/size.h"
26 class EmptySurfaceFactoryClient
: public SurfaceFactoryClient
{
28 void ReturnResources(const ReturnedResourceArray
& resources
) override
{}
31 void CreateSharedQuadState(RenderPass
* pass
,
32 const gfx::Transform
& transform
,
33 const gfx::Rect
& root_rect
) {
34 SharedQuadState
* child_shared_state
=
35 pass
->CreateAndAppendSharedQuadState();
36 child_shared_state
->SetAll(transform
,
38 root_rect
, root_rect
, false, 1.0f
,
39 SkXfermode::kSrcOver_Mode
, 0);
42 void CreateSolidColorDrawQuad(RenderPass
* pass
,
43 const gfx::Transform
& transform
,
44 const gfx::Rect
& root_rect
,
45 const gfx::Rect
& quad_rect
) {
46 CreateSharedQuadState(pass
, transform
, root_rect
);
47 SolidColorDrawQuad
* color_quad
=
48 pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
49 color_quad
->SetNew(pass
->shared_quad_state_list
.back(),
51 SK_ColorYELLOW
, false);
54 void CreateRenderPassDrawQuad(RenderPass
* pass
,
55 const gfx::Transform
& transform
,
56 const gfx::Rect
& root_rect
,
57 const gfx::Rect
& quad_rect
,
58 const RenderPassId
& render_pass_id
) {
59 CreateSharedQuadState(pass
, transform
, root_rect
);
60 RenderPassDrawQuad
* render_pass_quad
=
61 pass
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
62 render_pass_quad
->SetNew(pass
->shared_quad_state_list
.back(),
72 void CreateSurfaceDrawQuad(RenderPass
* pass
,
73 const gfx::Transform
& transform
,
74 const gfx::Rect
& root_rect
,
75 const gfx::Rect
& quad_rect
,
76 SurfaceId surface_id
) {
77 CreateSharedQuadState(pass
, transform
, root_rect
);
78 SurfaceDrawQuad
* surface_quad
=
79 pass
->CreateAndAppendDrawQuad
<SurfaceDrawQuad
>();
80 surface_quad
->SetNew(pass
->shared_quad_state_list
.back(),
85 scoped_ptr
<CompositorFrame
> CreateCompositorFrame(
86 const gfx::Rect
& root_rect
,
87 RenderPass
** render_pass
) {
88 RenderPassId
root_id(1, 1);
89 scoped_ptr
<RenderPass
> root_pass
= RenderPass::Create();
90 root_pass
->SetNew(root_id
, root_rect
, root_rect
, gfx::Transform());
92 scoped_ptr
<DelegatedFrameData
> root_delegated_frame_data(
93 new DelegatedFrameData
);
94 root_delegated_frame_data
->render_pass_list
.push_back(root_pass
.Pass());
95 scoped_ptr
<CompositorFrame
> root_frame(new CompositorFrame
);
96 root_frame
->delegated_frame_data
= root_delegated_frame_data
.Pass();
98 *render_pass
= root_frame
->delegated_frame_data
->render_pass_list
.back();
99 return root_frame
.Pass();
104 // This test verifies that hit testing on a surface that does not exist does
106 TEST(SurfaceHittestTest
, Hittest_BadCompositorFrameDoesNotCrash
) {
107 SurfaceManager manager
;
108 EmptySurfaceFactoryClient client
;
109 SurfaceFactory
factory(&manager
, &client
);
111 // Creates a root surface.
112 gfx::Rect
root_rect(300, 300);
113 RenderPass
* root_pass
= nullptr;
114 scoped_ptr
<CompositorFrame
> root_frame
=
115 CreateCompositorFrame(root_rect
, &root_pass
);
117 // Add a reference to a non-existant child surface on the root surface.
118 SurfaceIdAllocator
child_allocator(3);
119 SurfaceId child_surface_id
;
120 child_surface_id
.id
= 0xdeadbeef;
121 gfx::Rect
child_rect(200, 200);
122 CreateSurfaceDrawQuad(root_pass
,
128 // Submit the root frame.
129 SurfaceIdAllocator
root_allocator(2);
130 SurfaceId root_surface_id
= root_allocator
.GenerateId();
131 factory
.Create(root_surface_id
);
132 factory
.SubmitCompositorFrame(root_surface_id
, root_frame
.Pass(),
133 SurfaceFactory::DrawCallback());
136 SurfaceHittest
hittest(&manager
);
137 // It is expected this test will complete without crashes.
138 gfx::Point transformed_point
;
139 EXPECT_EQ(root_surface_id
,
140 hittest
.GetTargetSurfaceAtPoint(
141 root_surface_id
, gfx::Point(100, 100), &transformed_point
));
144 factory
.Destroy(root_surface_id
);
147 TEST(SurfaceHittestTest
, Hittest_SingleSurface
) {
148 SurfaceManager manager
;
149 EmptySurfaceFactoryClient client
;
150 SurfaceFactory
factory(&manager
, &client
);
152 // Creates a root surface.
153 gfx::Rect
root_rect(300, 300);
154 RenderPass
* root_pass
= nullptr;
155 scoped_ptr
<CompositorFrame
> root_frame
=
156 CreateCompositorFrame(root_rect
, &root_pass
);
158 // Submit the root frame.
159 SurfaceIdAllocator
root_allocator(2);
160 SurfaceId root_surface_id
= root_allocator
.GenerateId();
161 factory
.Create(root_surface_id
);
162 factory
.SubmitCompositorFrame(root_surface_id
, root_frame
.Pass(),
163 SurfaceFactory::DrawCallback());
166 SurfaceHittest
hittest(&manager
);
167 gfx::Point transformed_point
;
168 EXPECT_EQ(root_surface_id
,
169 hittest
.GetTargetSurfaceAtPoint(
170 root_surface_id
, gfx::Point(100, 100), &transformed_point
));
171 EXPECT_EQ(gfx::Point(100, 100), transformed_point
);
174 factory
.Destroy(root_surface_id
);
177 TEST(SurfaceHittestTest
, Hittest_ChildSurface
) {
178 SurfaceManager manager
;
179 EmptySurfaceFactoryClient client
;
180 SurfaceFactory
factory(&manager
, &client
);
182 // Creates a root surface.
183 gfx::Rect
root_rect(300, 300);
184 RenderPass
* root_pass
= nullptr;
185 scoped_ptr
<CompositorFrame
> root_frame
=
186 CreateCompositorFrame(root_rect
, &root_pass
);
188 // Add a reference to the child surface on the root surface.
189 SurfaceIdAllocator
child_allocator(3);
190 SurfaceId child_surface_id
= child_allocator
.GenerateId();
191 gfx::Rect
child_rect(200, 200);
192 CreateSurfaceDrawQuad(root_pass
,
193 gfx::Transform(1.0f
, 0.0f
, 0.0f
, 50.0f
,
194 0.0f
, 1.0f
, 0.0f
, 50.0f
,
195 0.0f
, 0.0f
, 1.0f
, 0.0f
,
196 0.0f
, 0.0f
, 0.0f
, 1.0f
),
201 // Submit the root frame.
202 SurfaceIdAllocator
root_allocator(2);
203 SurfaceId root_surface_id
= root_allocator
.GenerateId();
204 factory
.Create(root_surface_id
);
205 factory
.SubmitCompositorFrame(root_surface_id
, root_frame
.Pass(),
206 SurfaceFactory::DrawCallback());
208 // Creates a child surface.
209 RenderPass
* child_pass
= nullptr;
210 scoped_ptr
<CompositorFrame
> child_frame
=
211 CreateCompositorFrame(child_rect
, &child_pass
);
213 // Add a solid quad in the child surface.
214 gfx::Rect
child_solid_quad_rect(100, 100);
215 CreateSolidColorDrawQuad(child_pass
,
216 gfx::Transform(1.0f
, 0.0f
, 0.0f
, 50.0f
,
217 0.0f
, 1.0f
, 0.0f
, 50.0f
,
218 0.0f
, 0.0f
, 1.0f
, 0.0f
,
219 0.0f
, 0.0f
, 0.0f
, 1.0f
),
221 child_solid_quad_rect
);
224 factory
.Create(child_surface_id
);
225 factory
.SubmitCompositorFrame(child_surface_id
, child_frame
.Pass(),
226 SurfaceFactory::DrawCallback());
229 SurfaceHittest
hittest(&manager
);
230 gfx::Point transformed_point
;
231 EXPECT_EQ(root_surface_id
,
232 hittest
.GetTargetSurfaceAtPoint(
233 root_surface_id
, gfx::Point(10, 10), &transformed_point
));
234 EXPECT_EQ(gfx::Point(10, 10), transformed_point
);
235 EXPECT_EQ(root_surface_id
,
236 hittest
.GetTargetSurfaceAtPoint(
237 root_surface_id
, gfx::Point(99, 99), &transformed_point
));
238 EXPECT_EQ(gfx::Point(99, 99), transformed_point
);
239 EXPECT_EQ(child_surface_id
,
240 hittest
.GetTargetSurfaceAtPoint(
241 root_surface_id
, gfx::Point(100, 100), &transformed_point
));
242 EXPECT_EQ(gfx::Point(50, 50), transformed_point
);
243 EXPECT_EQ(child_surface_id
,
244 hittest
.GetTargetSurfaceAtPoint(
245 root_surface_id
, gfx::Point(199, 199), &transformed_point
));
246 EXPECT_EQ(gfx::Point(149, 149), transformed_point
);
247 EXPECT_EQ(root_surface_id
,
248 hittest
.GetTargetSurfaceAtPoint(
249 root_surface_id
, gfx::Point(200, 200), &transformed_point
));
250 EXPECT_EQ(gfx::Point(200, 200), transformed_point
);
251 EXPECT_EQ(root_surface_id
,
252 hittest
.GetTargetSurfaceAtPoint(
253 root_surface_id
, gfx::Point(290, 290), &transformed_point
));
254 EXPECT_EQ(gfx::Point(290, 290), transformed_point
);
257 factory
.Destroy(root_surface_id
);
258 factory
.Destroy(child_surface_id
);
261 // This test verifies that hit testing will progress to the next quad if it
262 // encounters an invalid RenderPassDrawQuad for whatever reason.
263 TEST(SurfaceHittestTest
, Hittest_InvalidRenderPassDrawQuad
) {
264 SurfaceManager manager
;
265 EmptySurfaceFactoryClient client
;
266 SurfaceFactory
factory(&manager
, &client
);
268 // Creates a root surface.
269 gfx::Rect
root_rect(300, 300);
270 RenderPass
* root_pass
= nullptr;
271 scoped_ptr
<CompositorFrame
> root_frame
=
272 CreateCompositorFrame(root_rect
, &root_pass
);
274 // Create a RenderPassDrawQuad to a non-existant RenderPass.
275 CreateRenderPassDrawQuad(root_pass
,
279 RenderPassId(1337, 1337));
281 // Add a reference to the child surface on the root surface.
282 SurfaceIdAllocator
child_allocator(3);
283 SurfaceId child_surface_id
= child_allocator
.GenerateId();
284 gfx::Rect
child_rect(200, 200);
285 CreateSurfaceDrawQuad(root_pass
,
286 gfx::Transform(1.0f
, 0.0f
, 0.0f
, 50.0f
,
287 0.0f
, 1.0f
, 0.0f
, 50.0f
,
288 0.0f
, 0.0f
, 1.0f
, 0.0f
,
289 0.0f
, 0.0f
, 0.0f
, 1.0f
),
294 // Submit the root frame.
295 SurfaceIdAllocator
root_allocator(2);
296 SurfaceId root_surface_id
= root_allocator
.GenerateId();
297 factory
.Create(root_surface_id
);
298 factory
.SubmitCompositorFrame(root_surface_id
, root_frame
.Pass(),
299 SurfaceFactory::DrawCallback());
301 // Creates a child surface.
302 RenderPass
* child_pass
= nullptr;
303 scoped_ptr
<CompositorFrame
> child_frame
=
304 CreateCompositorFrame(child_rect
, &child_pass
);
306 // Add a solid quad in the child surface.
307 gfx::Rect
child_solid_quad_rect(100, 100);
308 CreateSolidColorDrawQuad(child_pass
,
309 gfx::Transform(1.0f
, 0.0f
, 0.0f
, 50.0f
,
310 0.0f
, 1.0f
, 0.0f
, 50.0f
,
311 0.0f
, 0.0f
, 1.0f
, 0.0f
,
312 0.0f
, 0.0f
, 0.0f
, 1.0f
),
314 child_solid_quad_rect
);
317 factory
.Create(child_surface_id
);
318 factory
.SubmitCompositorFrame(child_surface_id
, child_frame
.Pass(),
319 SurfaceFactory::DrawCallback());
322 SurfaceHittest
hittest(&manager
);
323 gfx::Point transformed_point
;
324 EXPECT_EQ(root_surface_id
,
325 hittest
.GetTargetSurfaceAtPoint(
326 root_surface_id
, gfx::Point(10, 10), &transformed_point
));
327 EXPECT_EQ(gfx::Point(10, 10), transformed_point
);
328 EXPECT_EQ(root_surface_id
,
329 hittest
.GetTargetSurfaceAtPoint(
330 root_surface_id
, gfx::Point(99, 99), &transformed_point
));
331 EXPECT_EQ(gfx::Point(99, 99), transformed_point
);
332 EXPECT_EQ(child_surface_id
,
333 hittest
.GetTargetSurfaceAtPoint(
334 root_surface_id
, gfx::Point(100, 100), &transformed_point
));
335 EXPECT_EQ(gfx::Point(50, 50), transformed_point
);
336 EXPECT_EQ(child_surface_id
,
337 hittest
.GetTargetSurfaceAtPoint(
338 root_surface_id
, gfx::Point(199, 199), &transformed_point
));
339 EXPECT_EQ(gfx::Point(149, 149), transformed_point
);
340 EXPECT_EQ(root_surface_id
,
341 hittest
.GetTargetSurfaceAtPoint(
342 root_surface_id
, gfx::Point(200, 200), &transformed_point
));
343 EXPECT_EQ(gfx::Point(200, 200), transformed_point
);
344 EXPECT_EQ(root_surface_id
,
345 hittest
.GetTargetSurfaceAtPoint(
346 root_surface_id
, gfx::Point(290, 290), &transformed_point
));
347 EXPECT_EQ(gfx::Point(290, 290), transformed_point
);
350 factory
.Destroy(root_surface_id
);
351 factory
.Destroy(child_surface_id
);