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