software_output_device_ozone_unittest.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
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 "base/memory/scoped_ptr.h"
6#include "base/message_loop/message_loop.h"
7#include "cc/output/software_frame_data.h"
8#include "content/browser/compositor/software_output_device_ozone.h"
9#include "testing/gtest/include/gtest/gtest.h"
10#include "third_party/skia/include/core/SkSurface.h"
11#include "ui/compositor/compositor.h"
12#include "ui/compositor/test/context_factories_for_test.h"
13#include "ui/gfx/ozone/surface_factory_ozone.h"
14#include "ui/gfx/ozone/surface_ozone_canvas.h"
15#include "ui/gfx/size.h"
16#include "ui/gfx/skia_util.h"
17#include "ui/gfx/vsync_provider.h"
18#include "ui/gl/gl_implementation.h"
19
20namespace {
21
22class MockSurfaceOzone : public gfx::SurfaceOzoneCanvas {
23 public:
24  MockSurfaceOzone() {}
25  virtual ~MockSurfaceOzone() {}
26
27  // gfx::SurfaceOzoneCanvas overrides:
28  virtual bool ResizeCanvas(const gfx::Size& size) OVERRIDE {
29    surface_ = skia::AdoptRef(SkSurface::NewRaster(
30        SkImageInfo::MakeN32Premul(size.width(), size.height())));
31    return true;
32  }
33  virtual skia::RefPtr<SkCanvas> GetCanvas() OVERRIDE {
34    return skia::SharePtr(surface_->getCanvas());
35  }
36  virtual bool PresentCanvas() OVERRIDE {
37    NOTIMPLEMENTED();
38    return true;
39  }
40  virtual scoped_ptr<gfx::VSyncProvider> CreateVSyncProvider() OVERRIDE {
41    return scoped_ptr<gfx::VSyncProvider>();
42  }
43
44 private:
45  skia::RefPtr<SkSurface> surface_;
46
47  DISALLOW_COPY_AND_ASSIGN(MockSurfaceOzone);
48};
49
50class MockSurfaceFactoryOzone : public gfx::SurfaceFactoryOzone {
51 public:
52  MockSurfaceFactoryOzone() {}
53  virtual ~MockSurfaceFactoryOzone() {}
54
55  virtual HardwareState InitializeHardware() OVERRIDE {
56    return SurfaceFactoryOzone::INITIALIZED;
57  }
58
59  virtual void ShutdownHardware() OVERRIDE {}
60  virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE { return 1; }
61  virtual bool LoadEGLGLES2Bindings(
62      AddGLLibraryCallback add_gl_library,
63      SetGLGetProcAddressProcCallback set_gl_get_proc_address) OVERRIDE {
64    return false;
65  }
66  virtual scoped_ptr<gfx::SurfaceOzoneCanvas> CreateCanvasForWidget(
67      gfx::AcceleratedWidget widget) OVERRIDE {
68    return make_scoped_ptr<gfx::SurfaceOzoneCanvas>(new MockSurfaceOzone());
69  }
70
71 private:
72  DISALLOW_COPY_AND_ASSIGN(MockSurfaceFactoryOzone);
73};
74
75}  // namespace
76
77class SoftwareOutputDeviceOzoneTest : public testing::Test {
78 public:
79  SoftwareOutputDeviceOzoneTest();
80  virtual ~SoftwareOutputDeviceOzoneTest();
81
82  virtual void SetUp() OVERRIDE;
83  virtual void TearDown() OVERRIDE;
84
85 protected:
86  scoped_ptr<content::SoftwareOutputDeviceOzone> output_device_;
87  bool enable_pixel_output_;
88
89 private:
90  scoped_ptr<ui::Compositor> compositor_;
91  scoped_ptr<base::MessageLoop> message_loop_;
92  scoped_ptr<gfx::SurfaceFactoryOzone> surface_factory_;
93
94  DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceOzoneTest);
95};
96
97SoftwareOutputDeviceOzoneTest::SoftwareOutputDeviceOzoneTest()
98    : enable_pixel_output_(false) {
99  message_loop_.reset(new base::MessageLoopForUI);
100}
101
102SoftwareOutputDeviceOzoneTest::~SoftwareOutputDeviceOzoneTest() {
103}
104
105void SoftwareOutputDeviceOzoneTest::SetUp() {
106  ui::InitializeContextFactoryForTests(enable_pixel_output_);
107  ui::Compositor::Initialize();
108
109  surface_factory_.reset(new MockSurfaceFactoryOzone());
110  gfx::SurfaceFactoryOzone::SetInstance(surface_factory_.get());
111
112  const gfx::Size size(500, 400);
113  compositor_.reset(new ui::Compositor(
114      gfx::SurfaceFactoryOzone::GetInstance()->GetAcceleratedWidget()));
115  compositor_->SetScaleAndSize(1.0f, size);
116
117  output_device_.reset(new content::SoftwareOutputDeviceOzone(
118      compositor_.get()));
119  output_device_->Resize(size);
120}
121
122void SoftwareOutputDeviceOzoneTest::TearDown() {
123  output_device_.reset();
124  compositor_.reset();
125  surface_factory_.reset();
126  ui::TerminateContextFactoryForTests();
127  ui::Compositor::Terminate();
128}
129
130class SoftwareOutputDeviceOzonePixelTest
131    : public SoftwareOutputDeviceOzoneTest {
132 protected:
133  virtual void SetUp() OVERRIDE;
134};
135
136void SoftwareOutputDeviceOzonePixelTest::SetUp() {
137  enable_pixel_output_ = true;
138  SoftwareOutputDeviceOzoneTest::SetUp();
139}
140
141TEST_F(SoftwareOutputDeviceOzoneTest, CheckClipAfterBeginPaint) {
142  gfx::Rect damage(10, 10, 100, 100);
143  SkCanvas* canvas = output_device_->BeginPaint(damage);
144
145  SkIRect sk_bounds;
146  canvas->getClipDeviceBounds(&sk_bounds);
147
148  EXPECT_EQ(damage.ToString(), gfx::SkIRectToRect(sk_bounds).ToString());
149}
150
151TEST_F(SoftwareOutputDeviceOzoneTest, CheckClipAfterSecondBeginPaint) {
152  gfx::Rect damage(10, 10, 100, 100);
153  SkCanvas* canvas = output_device_->BeginPaint(damage);
154
155  cc::SoftwareFrameData frame;
156  output_device_->EndPaint(&frame);
157
158  damage = gfx::Rect(100, 100, 100, 100);
159  canvas = output_device_->BeginPaint(damage);
160  SkIRect sk_bounds;
161  canvas->getClipDeviceBounds(&sk_bounds);
162
163  EXPECT_EQ(damage.ToString(), gfx::SkIRectToRect(sk_bounds).ToString());
164}
165
166TEST_F(SoftwareOutputDeviceOzoneTest, CheckCorrectResizeBehavior) {
167  gfx::Rect damage(0, 0, 100, 100);
168  gfx::Size size(200, 100);
169  // Reduce size.
170  output_device_->Resize(size);
171
172  SkCanvas* canvas = output_device_->BeginPaint(damage);
173  gfx::Size canvas_size(canvas->getDeviceSize().width(),
174                        canvas->getDeviceSize().height());
175  EXPECT_EQ(size.ToString(), canvas_size.ToString());
176
177  size.SetSize(1000, 500);
178  // Increase size.
179  output_device_->Resize(size);
180
181  canvas = output_device_->BeginPaint(damage);
182  canvas_size.SetSize(canvas->getDeviceSize().width(),
183                      canvas->getDeviceSize().height());
184  EXPECT_EQ(size.ToString(), canvas_size.ToString());
185
186}
187
188TEST_F(SoftwareOutputDeviceOzonePixelTest, CheckCopyToBitmap) {
189  const int width = 6;
190  const int height = 4;
191  const gfx::Rect area(width, height);
192  output_device_->Resize(area.size());
193  SkCanvas* canvas = output_device_->BeginPaint(area);
194
195  // Clear the background to black.
196  canvas->drawColor(SK_ColorBLACK);
197
198  cc::SoftwareFrameData frame;
199  output_device_->EndPaint(&frame);
200
201  // Draw a white rectangle.
202  gfx::Rect damage(area.width() / 2, area.height() / 2);
203  canvas = output_device_->BeginPaint(damage);
204
205  canvas->drawColor(SK_ColorWHITE);
206
207  output_device_->EndPaint(&frame);
208
209  SkPMColor pixels[width * height];
210  output_device_->CopyToPixels(area, pixels);
211
212  // Check that the copied bitmap contains the same pixel values as what we
213  // painted.
214  const SkPMColor white = SkPreMultiplyColor(SK_ColorWHITE);
215  const SkPMColor black = SkPreMultiplyColor(SK_ColorBLACK);
216  for (int i = 0; i < area.height(); ++i) {
217    for (int j = 0; j < area.width(); ++j) {
218      if (j < damage.width() && i < damage.height())
219        EXPECT_EQ(white, pixels[i * area.width() + j]);
220      else
221        EXPECT_EQ(black, pixels[i * area.width() + j]);
222    }
223  }
224}
225