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