This sets up API to release OutputSurface from LTHClient.
[chromium-blink-merge.git] / cc / surfaces / surface_hittest_unittest.cc
blob5d9b1b2312fae849e6ca5257d6bf99ad079bb48b
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"
22 namespace cc {
24 namespace {
26 class EmptySurfaceFactoryClient : public SurfaceFactoryClient {
27 public:
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,
37 root_rect.size(),
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(),
50 quad_rect, quad_rect,
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(),
63 quad_rect, quad_rect,
64 render_pass_id,
65 ResourceId(),
66 gfx::Vector2dF(),
67 gfx::Size(),
68 FilterOperations(),
69 gfx::Vector2dF(),
70 FilterOperations());
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(),
81 quad_rect, quad_rect,
82 surface_id);
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();
102 } // namespace
104 // This test verifies that hit testing on a surface that does not exist does
105 // not crash.
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,
123 gfx::Transform(),
124 root_rect,
125 child_rect,
126 child_surface_id);
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),
197 root_rect,
198 child_rect,
199 child_surface_id);
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),
220 root_rect,
221 child_solid_quad_rect);
223 // Submit the frame.
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,
276 gfx::Transform(),
277 root_rect,
278 root_rect,
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),
290 root_rect,
291 child_rect,
292 child_surface_id);
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),
313 root_rect,
314 child_solid_quad_rect);
316 // Submit the frame.
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);
354 } // namespace cc