普通文本  |  336行  |  12.5 KB

// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cc/output/compositor_frame.h"
#include "cc/quads/render_pass.h"
#include "cc/quads/solid_color_draw_quad.h"
#include "cc/quads/surface_draw_quad.h"
#include "cc/surfaces/surface.h"
#include "cc/surfaces/surface_aggregator.h"
#include "cc/surfaces/surface_factory.h"
#include "cc/surfaces/surface_factory_client.h"
#include "cc/surfaces/surface_id_allocator.h"
#include "cc/surfaces/surface_manager.h"
#include "cc/test/pixel_comparator.h"
#include "cc/test/pixel_test.h"
#include "testing/gtest/include/gtest/gtest.h"

#if !defined(OS_ANDROID)

namespace cc {
namespace {

class EmptySurfaceFactoryClient : public SurfaceFactoryClient {
 public:
  virtual void ReturnResources(
      const ReturnedResourceArray& resources) OVERRIDE {}
};

class SurfacesPixelTest : public RendererPixelTest<GLRenderer> {
 public:
  SurfacesPixelTest() : allocator_(1u), factory_(&manager_, &client_) {}

 protected:
  SurfaceManager manager_;
  SurfaceIdAllocator allocator_;
  EmptySurfaceFactoryClient client_;
  SurfaceFactory factory_;
};

SharedQuadState* CreateAndAppendTestSharedQuadState(
    RenderPass* render_pass,
    const gfx::Transform& transform,
    const gfx::Size& size) {
  const gfx::Size content_bounds = size;
  const gfx::Rect visible_content_rect = gfx::Rect(size);
  const gfx::Rect clip_rect = gfx::Rect(size);
  bool is_clipped = false;
  float opacity = 1.f;
  const SkXfermode::Mode blend_mode = SkXfermode::kSrcOver_Mode;
  SharedQuadState* shared_state = render_pass->CreateAndAppendSharedQuadState();
  shared_state->SetAll(transform,
                       content_bounds,
                       visible_content_rect,
                       clip_rect,
                       is_clipped,
                       opacity,
                       blend_mode,
                       0);
  return shared_state;
}

// Draws a very simple frame with no surface references.
TEST_F(SurfacesPixelTest, DrawSimpleFrame) {
  gfx::Rect rect(device_viewport_size_);
  RenderPassId id(1, 1);
  scoped_ptr<RenderPass> pass = RenderPass::Create();
  pass->SetNew(id, rect, rect, gfx::Transform());

  CreateAndAppendTestSharedQuadState(
      pass.get(), gfx::Transform(), device_viewport_size_);

  SolidColorDrawQuad* color_quad =
      pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
  bool force_anti_aliasing_off = false;
  color_quad->SetNew(pass->shared_quad_state_list.back(),
                     rect,
                     rect,
                     SK_ColorGREEN,
                     force_anti_aliasing_off);

  scoped_ptr<DelegatedFrameData> delegated_frame_data(new DelegatedFrameData);
  delegated_frame_data->render_pass_list.push_back(pass.Pass());

  scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
  root_frame->delegated_frame_data = delegated_frame_data.Pass();

  SurfaceId root_surface_id = allocator_.GenerateId();
  factory_.Create(root_surface_id, device_viewport_size_);
  factory_.SubmitFrame(root_surface_id, root_frame.Pass(), base::Closure());

  SurfaceAggregator aggregator(&manager_, resource_provider_.get());
  scoped_ptr<CompositorFrame> aggregated_frame =
      aggregator.Aggregate(root_surface_id);
  factory_.Destroy(root_surface_id);

  bool discard_alpha = false;
  ExactPixelComparator pixel_comparator(discard_alpha);
  RenderPassList* pass_list =
      &aggregated_frame->delegated_frame_data->render_pass_list;
  EXPECT_TRUE(RunPixelTest(pass_list,
                           base::FilePath(FILE_PATH_LITERAL("green.png")),
                           pixel_comparator));
}

// Draws a frame with simple surface embedding.
TEST_F(SurfacesPixelTest, DrawSimpleAggregatedFrame) {
  gfx::Size child_size(200, 100);
  SurfaceId child_surface_id = allocator_.GenerateId();
  SurfaceId root_surface_id = allocator_.GenerateId();
  factory_.Create(child_surface_id, child_size);
  factory_.Create(root_surface_id, device_viewport_size_);
  {
    gfx::Rect rect(device_viewport_size_);
    RenderPassId id(1, 1);
    scoped_ptr<RenderPass> pass = RenderPass::Create();
    pass->SetNew(id, rect, rect, gfx::Transform());

    CreateAndAppendTestSharedQuadState(
        pass.get(), gfx::Transform(), device_viewport_size_);

    SurfaceDrawQuad* surface_quad =
        pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
    surface_quad->SetNew(pass->shared_quad_state_list.back(),
                         gfx::Rect(child_size),
                         gfx::Rect(child_size),
                         child_surface_id);

    SolidColorDrawQuad* color_quad =
        pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
    bool force_anti_aliasing_off = false;
    color_quad->SetNew(pass->shared_quad_state_list.back(),
                       rect,
                       rect,
                       SK_ColorYELLOW,
                       force_anti_aliasing_off);

    scoped_ptr<DelegatedFrameData> delegated_frame_data(new DelegatedFrameData);
    delegated_frame_data->render_pass_list.push_back(pass.Pass());

    scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
    root_frame->delegated_frame_data = delegated_frame_data.Pass();

    factory_.SubmitFrame(root_surface_id, root_frame.Pass(), base::Closure());
  }

  {
    gfx::Rect rect(child_size);
    RenderPassId id(1, 1);
    scoped_ptr<RenderPass> pass = RenderPass::Create();
    pass->SetNew(id, rect, rect, gfx::Transform());

    CreateAndAppendTestSharedQuadState(
        pass.get(), gfx::Transform(), child_size);

    SolidColorDrawQuad* color_quad =
        pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
    bool force_anti_aliasing_off = false;
    color_quad->SetNew(pass->shared_quad_state_list.back(),
                       rect,
                       rect,
                       SK_ColorBLUE,
                       force_anti_aliasing_off);

    scoped_ptr<DelegatedFrameData> delegated_frame_data(new DelegatedFrameData);
    delegated_frame_data->render_pass_list.push_back(pass.Pass());

    scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
    child_frame->delegated_frame_data = delegated_frame_data.Pass();

    factory_.SubmitFrame(child_surface_id, child_frame.Pass(), base::Closure());
  }

  SurfaceAggregator aggregator(&manager_, resource_provider_.get());
  scoped_ptr<CompositorFrame> aggregated_frame =
      aggregator.Aggregate(root_surface_id);

  bool discard_alpha = false;
  ExactPixelComparator pixel_comparator(discard_alpha);
  RenderPassList* pass_list =
      &aggregated_frame->delegated_frame_data->render_pass_list;
  EXPECT_TRUE(RunPixelTest(pass_list,
                           base::FilePath(FILE_PATH_LITERAL("blue_yellow.png")),
                           pixel_comparator));
  factory_.Destroy(root_surface_id);
  factory_.Destroy(child_surface_id);
}

// Tests a surface quad that has a non-identity transform into its pass.
TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) {
  gfx::Size child_size(100, 200);
  gfx::Size quad_size(100, 100);
  // Structure:
  // root (200x200) -> left_child (100x200 @ 0x0,
  //                   right_child (100x200 @ 0x100)
  //   left_child -> top_green_quad (100x100 @ 0x0),
  //                 bottom_blue_quad (100x100 @ 0x100)
  //   right_child -> top_blue_quad (100x100 @ 0x0),
  //                  bottom_green_quad (100x100 @ 0x100)
  SurfaceId left_child_id = allocator_.GenerateId();
  SurfaceId right_child_id = allocator_.GenerateId();
  SurfaceId root_surface_id = allocator_.GenerateId();
  factory_.Create(left_child_id, child_size);
  factory_.Create(right_child_id, child_size);
  factory_.Create(root_surface_id, device_viewport_size_);

  {
    gfx::Rect rect(device_viewport_size_);
    RenderPassId id(1, 1);
    scoped_ptr<RenderPass> pass = RenderPass::Create();
    pass->SetNew(id, rect, rect, gfx::Transform());

    gfx::Transform surface_transform;
    CreateAndAppendTestSharedQuadState(
        pass.get(), surface_transform, device_viewport_size_);

    SurfaceDrawQuad* left_surface_quad =
        pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
    left_surface_quad->SetNew(pass->shared_quad_state_list.back(),
                              gfx::Rect(child_size),
                              gfx::Rect(child_size),
                              left_child_id);

    surface_transform.Translate(100, 0);
    CreateAndAppendTestSharedQuadState(
        pass.get(), surface_transform, device_viewport_size_);

    SurfaceDrawQuad* right_surface_quad =
        pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
    right_surface_quad->SetNew(pass->shared_quad_state_list.back(),
                               gfx::Rect(child_size),
                               gfx::Rect(child_size),
                               right_child_id);

    scoped_ptr<DelegatedFrameData> delegated_frame_data(new DelegatedFrameData);
    delegated_frame_data->render_pass_list.push_back(pass.Pass());

    scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
    root_frame->delegated_frame_data = delegated_frame_data.Pass();

    factory_.SubmitFrame(root_surface_id, root_frame.Pass(), base::Closure());
  }

  {
    gfx::Rect rect(child_size);
    RenderPassId id(1, 1);
    scoped_ptr<RenderPass> pass = RenderPass::Create();
    pass->SetNew(id, rect, rect, gfx::Transform());

    CreateAndAppendTestSharedQuadState(
        pass.get(), gfx::Transform(), child_size);

    SolidColorDrawQuad* top_color_quad =
        pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
    bool force_anti_aliasing_off = false;
    top_color_quad->SetNew(pass->shared_quad_state_list.back(),
                           gfx::Rect(quad_size),
                           gfx::Rect(quad_size),
                           SK_ColorGREEN,
                           force_anti_aliasing_off);

    SolidColorDrawQuad* bottom_color_quad =
        pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
    bottom_color_quad->SetNew(pass->shared_quad_state_list.back(),
                              gfx::Rect(0, 100, 100, 100),
                              gfx::Rect(0, 100, 100, 100),
                              SK_ColorBLUE,
                              force_anti_aliasing_off);

    scoped_ptr<DelegatedFrameData> delegated_frame_data(new DelegatedFrameData);
    delegated_frame_data->render_pass_list.push_back(pass.Pass());

    scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
    child_frame->delegated_frame_data = delegated_frame_data.Pass();

    factory_.SubmitFrame(left_child_id, child_frame.Pass(), base::Closure());
  }

  {
    gfx::Rect rect(child_size);
    RenderPassId id(1, 1);
    scoped_ptr<RenderPass> pass = RenderPass::Create();
    pass->SetNew(id, rect, rect, gfx::Transform());

    CreateAndAppendTestSharedQuadState(
        pass.get(), gfx::Transform(), child_size);

    SolidColorDrawQuad* top_color_quad =
        pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
    bool force_anti_aliasing_off = false;
    top_color_quad->SetNew(pass->shared_quad_state_list.back(),
                           gfx::Rect(quad_size),
                           gfx::Rect(quad_size),
                           SK_ColorBLUE,
                           force_anti_aliasing_off);

    SolidColorDrawQuad* bottom_color_quad =
        pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
    bottom_color_quad->SetNew(pass->shared_quad_state_list.back(),
                              gfx::Rect(0, 100, 100, 100),
                              gfx::Rect(0, 100, 100, 100),
                              SK_ColorGREEN,
                              force_anti_aliasing_off);

    scoped_ptr<DelegatedFrameData> delegated_frame_data(new DelegatedFrameData);
    delegated_frame_data->render_pass_list.push_back(pass.Pass());

    scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
    child_frame->delegated_frame_data = delegated_frame_data.Pass();

    factory_.SubmitFrame(right_child_id, child_frame.Pass(), base::Closure());
  }

  SurfaceAggregator aggregator(&manager_, resource_provider_.get());
  scoped_ptr<CompositorFrame> aggregated_frame =
      aggregator.Aggregate(root_surface_id);

  bool discard_alpha = false;
  ExactPixelComparator pixel_comparator(discard_alpha);
  RenderPassList* pass_list =
      &aggregated_frame->delegated_frame_data->render_pass_list;
  EXPECT_TRUE(RunPixelTest(
      pass_list,
      base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
      pixel_comparator));

  factory_.Destroy(root_surface_id);
  factory_.Destroy(left_child_id);
  factory_.Destroy(right_child_id);
}

}  // namespace
}  // namespace cc

#endif  // !defined(OS_ANDROID)