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.
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/size.h"
15 #include "ui/gfx/skia_util.h"
16 #include "ui/gfx/vsync_provider.h"
17 #include "ui/gl/gl_implementation.h"
21 class MockSurfaceFactoryOzone
: public gfx::SurfaceFactoryOzone
{
23 MockSurfaceFactoryOzone() {}
24 virtual ~MockSurfaceFactoryOzone() {}
26 virtual HardwareState
InitializeHardware() OVERRIDE
{
27 return SurfaceFactoryOzone::INITIALIZED
;
30 virtual void ShutdownHardware() OVERRIDE
{}
31 virtual gfx::AcceleratedWidget
GetAcceleratedWidget() OVERRIDE
{ return 1; }
32 virtual gfx::AcceleratedWidget
RealizeAcceleratedWidget(
33 gfx::AcceleratedWidget w
) OVERRIDE
{ return w
; }
34 virtual bool LoadEGLGLES2Bindings(
35 AddGLLibraryCallback add_gl_library
,
36 SetGLGetProcAddressProcCallback set_gl_get_proc_address
) OVERRIDE
{
39 virtual bool AttemptToResizeAcceleratedWidget(
40 gfx::AcceleratedWidget w
, const gfx::Rect
& bounds
) OVERRIDE
{
41 surface_
= skia::AdoptRef(SkSurface::NewRaster(
42 SkImageInfo::MakeN32Premul(bounds
.width(), bounds
.height())));
45 virtual SkCanvas
* GetCanvasForWidget(gfx::AcceleratedWidget w
) OVERRIDE
{
46 return surface_
->getCanvas();
48 virtual scoped_ptr
<gfx::VSyncProvider
> CreateVSyncProvider(
49 gfx::AcceleratedWidget w
) OVERRIDE
{
50 return scoped_ptr
<gfx::VSyncProvider
>();
53 skia::RefPtr
<SkSurface
> surface_
;
55 DISALLOW_COPY_AND_ASSIGN(MockSurfaceFactoryOzone
);
60 class SoftwareOutputDeviceOzoneTest
: public testing::Test
{
62 SoftwareOutputDeviceOzoneTest();
63 virtual ~SoftwareOutputDeviceOzoneTest();
65 virtual void SetUp() OVERRIDE
;
66 virtual void TearDown() OVERRIDE
;
69 scoped_ptr
<content::SoftwareOutputDeviceOzone
> output_device_
;
70 bool enable_pixel_output_
;
73 scoped_ptr
<ui::Compositor
> compositor_
;
74 scoped_ptr
<base::MessageLoop
> message_loop_
;
75 scoped_ptr
<gfx::SurfaceFactoryOzone
> surface_factory_
;
77 DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceOzoneTest
);
80 SoftwareOutputDeviceOzoneTest::SoftwareOutputDeviceOzoneTest()
81 : enable_pixel_output_(false) {
82 message_loop_
.reset(new base::MessageLoopForUI
);
85 SoftwareOutputDeviceOzoneTest::~SoftwareOutputDeviceOzoneTest() {
88 void SoftwareOutputDeviceOzoneTest::SetUp() {
89 ui::InitializeContextFactoryForTests(enable_pixel_output_
);
90 ui::Compositor::Initialize();
92 surface_factory_
.reset(new MockSurfaceFactoryOzone());
93 gfx::SurfaceFactoryOzone::SetInstance(surface_factory_
.get());
95 const gfx::Size
size(500, 400);
96 compositor_
.reset(new ui::Compositor(
97 gfx::SurfaceFactoryOzone::GetInstance()->GetAcceleratedWidget()));
98 compositor_
->SetScaleAndSize(1.0f
, size
);
100 output_device_
.reset(new content::SoftwareOutputDeviceOzone(
102 output_device_
->Resize(size
);
105 void SoftwareOutputDeviceOzoneTest::TearDown() {
106 output_device_
.reset();
108 surface_factory_
.reset();
109 ui::TerminateContextFactoryForTests();
110 ui::Compositor::Terminate();
113 class SoftwareOutputDeviceOzonePixelTest
114 : public SoftwareOutputDeviceOzoneTest
{
116 virtual void SetUp() OVERRIDE
;
119 void SoftwareOutputDeviceOzonePixelTest::SetUp() {
120 enable_pixel_output_
= true;
121 SoftwareOutputDeviceOzoneTest::SetUp();
124 TEST_F(SoftwareOutputDeviceOzoneTest
, CheckClipAfterBeginPaint
) {
125 gfx::Rect
damage(10, 10, 100, 100);
126 SkCanvas
* canvas
= output_device_
->BeginPaint(damage
);
129 canvas
->getClipDeviceBounds(&sk_bounds
);
131 EXPECT_EQ(damage
.ToString(), gfx::SkIRectToRect(sk_bounds
).ToString());
134 TEST_F(SoftwareOutputDeviceOzoneTest
, CheckClipAfterSecondBeginPaint
) {
135 gfx::Rect
damage(10, 10, 100, 100);
136 SkCanvas
* canvas
= output_device_
->BeginPaint(damage
);
138 cc::SoftwareFrameData frame
;
139 output_device_
->EndPaint(&frame
);
141 damage
= gfx::Rect(100, 100, 100, 100);
142 canvas
= output_device_
->BeginPaint(damage
);
144 canvas
->getClipDeviceBounds(&sk_bounds
);
146 EXPECT_EQ(damage
.ToString(), gfx::SkIRectToRect(sk_bounds
).ToString());
149 TEST_F(SoftwareOutputDeviceOzoneTest
, CheckCorrectResizeBehavior
) {
150 gfx::Rect
damage(0, 0, 100, 100);
151 gfx::Size
size(200, 100);
153 output_device_
->Resize(size
);
155 SkCanvas
* canvas
= output_device_
->BeginPaint(damage
);
156 gfx::Size
canvas_size(canvas
->getDeviceSize().width(),
157 canvas
->getDeviceSize().height());
158 EXPECT_EQ(size
.ToString(), canvas_size
.ToString());
160 size
.SetSize(1000, 500);
162 output_device_
->Resize(size
);
164 canvas
= output_device_
->BeginPaint(damage
);
165 canvas_size
.SetSize(canvas
->getDeviceSize().width(),
166 canvas
->getDeviceSize().height());
167 EXPECT_EQ(size
.ToString(), canvas_size
.ToString());
171 TEST_F(SoftwareOutputDeviceOzonePixelTest
, CheckCopyToBitmap
) {
173 const int height
= 4;
174 const gfx::Rect
area(width
, height
);
175 output_device_
->Resize(area
.size());
176 SkCanvas
* canvas
= output_device_
->BeginPaint(area
);
178 // Clear the background to black.
179 canvas
->drawColor(SK_ColorBLACK
);
181 cc::SoftwareFrameData frame
;
182 output_device_
->EndPaint(&frame
);
184 // Draw a white rectangle.
185 gfx::Rect
damage(area
.width() / 2, area
.height() / 2);
186 canvas
= output_device_
->BeginPaint(damage
);
188 canvas
->drawColor(SK_ColorWHITE
);
190 output_device_
->EndPaint(&frame
);
192 SkPMColor pixels
[width
* height
];
193 output_device_
->CopyToPixels(area
, pixels
);
195 // Check that the copied bitmap contains the same pixel values as what we
197 const SkPMColor white
= SkPreMultiplyColor(SK_ColorWHITE
);
198 const SkPMColor black
= SkPreMultiplyColor(SK_ColorBLACK
);
199 for (int i
= 0; i
< area
.height(); ++i
) {
200 for (int j
= 0; j
< area
.width(); ++j
) {
201 if (j
< damage
.width() && i
< damage
.height())
202 EXPECT_EQ(white
, pixels
[i
* area
.width() + j
]);
204 EXPECT_EQ(black
, pixels
[i
* area
.width() + j
]);