1// Copyright 2014 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.
4
5#include "cc/output/compositor_frame.h"
6#include "cc/quads/render_pass.h"
7#include "cc/quads/solid_color_draw_quad.h"
8#include "cc/quads/surface_draw_quad.h"
9#include "cc/surfaces/surface.h"
10#include "cc/surfaces/surface_aggregator.h"
11#include "cc/surfaces/surface_manager.h"
12#include "cc/test/pixel_comparator.h"
13#include "cc/test/pixel_test.h"
14#include "testing/gtest/include/gtest/gtest.h"
15
16#if !defined(OS_ANDROID)
17
18namespace cc {
19namespace {
20
21class SurfacesPixelTest : public RendererPixelTest<GLRenderer> {
22 protected:
23  SurfaceManager manager_;
24};
25
26SharedQuadState* CreateAndAppendTestSharedQuadState(
27    RenderPass* render_pass,
28    const gfx::Transform& transform,
29    const gfx::Size& size) {
30  const gfx::Size content_bounds = size;
31  const gfx::Rect visible_content_rect = gfx::Rect(size);
32  const gfx::Rect clip_rect = gfx::Rect(size);
33  bool is_clipped = false;
34  float opacity = 1.f;
35  const SkXfermode::Mode blend_mode = SkXfermode::kSrcOver_Mode;
36  SharedQuadState* shared_state = render_pass->CreateAndAppendSharedQuadState();
37  shared_state->SetAll(transform,
38                       content_bounds,
39                       visible_content_rect,
40                       clip_rect,
41                       is_clipped,
42                       opacity,
43                       blend_mode,
44                       0);
45  return shared_state;
46}
47
48// Draws a very simple frame with no surface references.
49TEST_F(SurfacesPixelTest, DrawSimpleFrame) {
50  gfx::Rect rect(device_viewport_size_);
51  RenderPass::Id id(1, 1);
52  scoped_ptr<RenderPass> pass = RenderPass::Create();
53  pass->SetNew(id, rect, rect, gfx::Transform());
54
55  CreateAndAppendTestSharedQuadState(
56      pass.get(), gfx::Transform(), device_viewport_size_);
57
58  scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create();
59  bool force_anti_aliasing_off = false;
60  color_quad->SetNew(pass->shared_quad_state_list.back(),
61                     rect,
62                     rect,
63                     SK_ColorGREEN,
64                     force_anti_aliasing_off);
65  pass->quad_list.push_back(color_quad.PassAs<DrawQuad>());
66
67  scoped_ptr<DelegatedFrameData> delegated_frame_data(new DelegatedFrameData);
68  delegated_frame_data->render_pass_list.push_back(pass.Pass());
69
70  scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
71  root_frame->delegated_frame_data = delegated_frame_data.Pass();
72
73  Surface root_surface(&manager_, NULL, device_viewport_size_);
74  root_surface.QueueFrame(root_frame.Pass());
75
76  SurfaceAggregator aggregator(&manager_);
77  scoped_ptr<CompositorFrame> aggregated_frame =
78      aggregator.Aggregate(root_surface.surface_id());
79
80  bool discard_alpha = false;
81  ExactPixelComparator pixel_comparator(discard_alpha);
82  RenderPassList* pass_list =
83      &aggregated_frame->delegated_frame_data->render_pass_list;
84  EXPECT_TRUE(RunPixelTest(pass_list,
85                           base::FilePath(FILE_PATH_LITERAL("green.png")),
86                           pixel_comparator));
87}
88
89// Draws a frame with simple surface embedding.
90TEST_F(SurfacesPixelTest, DrawSimpleAggregatedFrame) {
91  gfx::Size child_size(200, 100);
92  Surface child_surface(&manager_, NULL, child_size);
93  Surface root_surface(&manager_, NULL, device_viewport_size_);
94
95  {
96    gfx::Rect rect(device_viewport_size_);
97    RenderPass::Id id(1, 1);
98    scoped_ptr<RenderPass> pass = RenderPass::Create();
99    pass->SetNew(id, rect, rect, gfx::Transform());
100
101    CreateAndAppendTestSharedQuadState(
102        pass.get(), gfx::Transform(), device_viewport_size_);
103
104    scoped_ptr<SurfaceDrawQuad> surface_quad = SurfaceDrawQuad::Create();
105    surface_quad->SetNew(pass->shared_quad_state_list.back(),
106                         gfx::Rect(child_size),
107                         gfx::Rect(child_size),
108                         child_surface.surface_id());
109    pass->quad_list.push_back(surface_quad.PassAs<DrawQuad>());
110
111    scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create();
112    bool force_anti_aliasing_off = false;
113    color_quad->SetNew(pass->shared_quad_state_list.back(),
114                       rect,
115                       rect,
116                       SK_ColorYELLOW,
117                       force_anti_aliasing_off);
118    pass->quad_list.push_back(color_quad.PassAs<DrawQuad>());
119
120    scoped_ptr<DelegatedFrameData> delegated_frame_data(new DelegatedFrameData);
121    delegated_frame_data->render_pass_list.push_back(pass.Pass());
122
123    scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
124    root_frame->delegated_frame_data = delegated_frame_data.Pass();
125
126    root_surface.QueueFrame(root_frame.Pass());
127  }
128
129  {
130    gfx::Rect rect(child_size);
131    RenderPass::Id id(1, 1);
132    scoped_ptr<RenderPass> pass = RenderPass::Create();
133    pass->SetNew(id, rect, rect, gfx::Transform());
134
135    CreateAndAppendTestSharedQuadState(
136        pass.get(), gfx::Transform(), child_size);
137
138    scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create();
139    bool force_anti_aliasing_off = false;
140    color_quad->SetNew(pass->shared_quad_state_list.back(),
141                       rect,
142                       rect,
143                       SK_ColorBLUE,
144                       force_anti_aliasing_off);
145    pass->quad_list.push_back(color_quad.PassAs<DrawQuad>());
146
147    scoped_ptr<DelegatedFrameData> delegated_frame_data(new DelegatedFrameData);
148    delegated_frame_data->render_pass_list.push_back(pass.Pass());
149
150    scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
151    child_frame->delegated_frame_data = delegated_frame_data.Pass();
152
153    child_surface.QueueFrame(child_frame.Pass());
154  }
155
156  SurfaceAggregator aggregator(&manager_);
157  scoped_ptr<CompositorFrame> aggregated_frame =
158      aggregator.Aggregate(root_surface.surface_id());
159
160  bool discard_alpha = false;
161  ExactPixelComparator pixel_comparator(discard_alpha);
162  RenderPassList* pass_list =
163      &aggregated_frame->delegated_frame_data->render_pass_list;
164  EXPECT_TRUE(RunPixelTest(pass_list,
165                           base::FilePath(FILE_PATH_LITERAL("blue_yellow.png")),
166                           pixel_comparator));
167}
168
169// Tests a surface quad that has a non-identity transform into its pass.
170TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) {
171  gfx::Size child_size(100, 200);
172  gfx::Size quad_size(100, 100);
173  // Structure:
174  // root (200x200) -> left_child (100x200 @ 0x0,
175  //                   right_child (100x200 @ 0x100)
176  //   left_child -> top_green_quad (100x100 @ 0x0),
177  //                 bottom_blue_quad (100x100 @ 0x100)
178  //   right_child -> top_blue_quad (100x100 @ 0x0),
179  //                  bottom_green_quad (100x100 @ 0x100)
180  Surface left_child(&manager_, NULL, child_size);
181  Surface right_child(&manager_, NULL, child_size);
182  Surface root_surface(&manager_, NULL, device_viewport_size_);
183
184  {
185    gfx::Rect rect(device_viewport_size_);
186    RenderPass::Id id(1, 1);
187    scoped_ptr<RenderPass> pass = RenderPass::Create();
188    pass->SetNew(id, rect, rect, gfx::Transform());
189
190    gfx::Transform surface_transform;
191    CreateAndAppendTestSharedQuadState(
192        pass.get(), surface_transform, device_viewport_size_);
193
194    scoped_ptr<SurfaceDrawQuad> left_surface_quad = SurfaceDrawQuad::Create();
195    left_surface_quad->SetNew(pass->shared_quad_state_list.back(),
196                              gfx::Rect(child_size),
197                              gfx::Rect(child_size),
198                              left_child.surface_id());
199    pass->quad_list.push_back(left_surface_quad.PassAs<DrawQuad>());
200
201    surface_transform.Translate(100, 0);
202    CreateAndAppendTestSharedQuadState(
203        pass.get(), surface_transform, device_viewport_size_);
204
205    scoped_ptr<SurfaceDrawQuad> right_surface_quad = SurfaceDrawQuad::Create();
206    right_surface_quad->SetNew(pass->shared_quad_state_list.back(),
207                               gfx::Rect(child_size),
208                               gfx::Rect(child_size),
209                               right_child.surface_id());
210    pass->quad_list.push_back(right_surface_quad.PassAs<DrawQuad>());
211
212    scoped_ptr<DelegatedFrameData> delegated_frame_data(new DelegatedFrameData);
213    delegated_frame_data->render_pass_list.push_back(pass.Pass());
214
215    scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
216    root_frame->delegated_frame_data = delegated_frame_data.Pass();
217
218    root_surface.QueueFrame(root_frame.Pass());
219  }
220
221  {
222    gfx::Rect rect(child_size);
223    RenderPass::Id id(1, 1);
224    scoped_ptr<RenderPass> pass = RenderPass::Create();
225    pass->SetNew(id, rect, rect, gfx::Transform());
226
227    CreateAndAppendTestSharedQuadState(
228        pass.get(), gfx::Transform(), child_size);
229
230    scoped_ptr<SolidColorDrawQuad> top_color_quad =
231        SolidColorDrawQuad::Create();
232    bool force_anti_aliasing_off = false;
233    top_color_quad->SetNew(pass->shared_quad_state_list.back(),
234                           gfx::Rect(quad_size),
235                           gfx::Rect(quad_size),
236                           SK_ColorGREEN,
237                           force_anti_aliasing_off);
238    pass->quad_list.push_back(top_color_quad.PassAs<DrawQuad>());
239
240    scoped_ptr<SolidColorDrawQuad> bottom_color_quad =
241        SolidColorDrawQuad::Create();
242    bottom_color_quad->SetNew(pass->shared_quad_state_list.back(),
243                              gfx::Rect(0, 100, 100, 100),
244                              gfx::Rect(0, 100, 100, 100),
245                              SK_ColorBLUE,
246                              force_anti_aliasing_off);
247    pass->quad_list.push_back(bottom_color_quad.PassAs<DrawQuad>());
248
249    scoped_ptr<DelegatedFrameData> delegated_frame_data(new DelegatedFrameData);
250    delegated_frame_data->render_pass_list.push_back(pass.Pass());
251
252    scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
253    child_frame->delegated_frame_data = delegated_frame_data.Pass();
254
255    left_child.QueueFrame(child_frame.Pass());
256  }
257
258  {
259    gfx::Rect rect(child_size);
260    RenderPass::Id id(1, 1);
261    scoped_ptr<RenderPass> pass = RenderPass::Create();
262    pass->SetNew(id, rect, rect, gfx::Transform());
263
264    CreateAndAppendTestSharedQuadState(
265        pass.get(), gfx::Transform(), child_size);
266
267    scoped_ptr<SolidColorDrawQuad> top_color_quad =
268        SolidColorDrawQuad::Create();
269    bool force_anti_aliasing_off = false;
270    top_color_quad->SetNew(pass->shared_quad_state_list.back(),
271                           gfx::Rect(quad_size),
272                           gfx::Rect(quad_size),
273                           SK_ColorBLUE,
274                           force_anti_aliasing_off);
275    pass->quad_list.push_back(top_color_quad.PassAs<DrawQuad>());
276
277    scoped_ptr<SolidColorDrawQuad> bottom_color_quad =
278        SolidColorDrawQuad::Create();
279    bottom_color_quad->SetNew(pass->shared_quad_state_list.back(),
280                              gfx::Rect(0, 100, 100, 100),
281                              gfx::Rect(0, 100, 100, 100),
282                              SK_ColorGREEN,
283                              force_anti_aliasing_off);
284    pass->quad_list.push_back(bottom_color_quad.PassAs<DrawQuad>());
285
286    scoped_ptr<DelegatedFrameData> delegated_frame_data(new DelegatedFrameData);
287    delegated_frame_data->render_pass_list.push_back(pass.Pass());
288
289    scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
290    child_frame->delegated_frame_data = delegated_frame_data.Pass();
291
292    right_child.QueueFrame(child_frame.Pass());
293  }
294
295  SurfaceAggregator aggregator(&manager_);
296  scoped_ptr<CompositorFrame> aggregated_frame =
297      aggregator.Aggregate(root_surface.surface_id());
298
299  bool discard_alpha = false;
300  ExactPixelComparator pixel_comparator(discard_alpha);
301  RenderPassList* pass_list =
302      &aggregated_frame->delegated_frame_data->render_pass_list;
303  EXPECT_TRUE(RunPixelTest(
304      pass_list,
305      base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
306      pixel_comparator));
307}
308
309}  // namespace
310}  // namespace cc
311
312#endif  // !defined(OS_ANDROID)
313