| // Copyright 2013 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 "base/memory/scoped_ptr.h" |
| #include "base/message_loop/message_loop.h" |
| #include "cc/output/software_frame_data.h" |
| #include "content/browser/aura/software_output_device_ozone.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/skia/include/core/SkBitmapDevice.h" |
| #include "ui/compositor/compositor.h" |
| #include "ui/compositor/test/context_factories_for_test.h" |
| #include "ui/gfx/ozone/surface_factory_ozone.h" |
| #include "ui/gfx/size.h" |
| #include "ui/gfx/skia_util.h" |
| #include "ui/gl/gl_implementation.h" |
| |
| namespace { |
| |
| class MockSurfaceFactoryOzone : public gfx::SurfaceFactoryOzone { |
| public: |
| MockSurfaceFactoryOzone() {} |
| virtual ~MockSurfaceFactoryOzone() {} |
| |
| virtual HardwareState InitializeHardware() OVERRIDE { |
| return SurfaceFactoryOzone::INITIALIZED; |
| } |
| |
| virtual void ShutdownHardware() OVERRIDE {} |
| virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE { return 1; } |
| virtual gfx::AcceleratedWidget RealizeAcceleratedWidget( |
| gfx::AcceleratedWidget w) OVERRIDE { return w; } |
| virtual bool LoadEGLGLES2Bindings() OVERRIDE { return false; } |
| virtual bool AttemptToResizeAcceleratedWidget( |
| gfx::AcceleratedWidget w, const gfx::Rect& bounds) OVERRIDE { |
| device_ = skia::AdoptRef(new SkBitmapDevice(SkBitmap::kARGB_8888_Config, |
| bounds.width(), |
| bounds.height(), |
| true)); |
| canvas_ = skia::AdoptRef(new SkCanvas(device_.get())); |
| return true; |
| } |
| virtual SkCanvas* GetCanvasForWidget(gfx::AcceleratedWidget w) OVERRIDE { |
| return canvas_.get(); |
| } |
| virtual gfx::VSyncProvider* GetVSyncProvider( |
| gfx::AcceleratedWidget w) OVERRIDE { |
| return NULL; |
| } |
| private: |
| skia::RefPtr<SkBitmapDevice> device_; |
| skia::RefPtr<SkCanvas> canvas_; |
| |
| DISALLOW_COPY_AND_ASSIGN(MockSurfaceFactoryOzone); |
| }; |
| |
| } // namespace |
| |
| class SoftwareOutputDeviceOzoneTest : public testing::Test { |
| public: |
| SoftwareOutputDeviceOzoneTest(); |
| virtual ~SoftwareOutputDeviceOzoneTest(); |
| |
| virtual void SetUp() OVERRIDE; |
| virtual void TearDown() OVERRIDE; |
| |
| protected: |
| scoped_ptr<content::SoftwareOutputDeviceOzone> output_device_; |
| |
| private: |
| scoped_ptr<ui::Compositor> compositor_; |
| scoped_ptr<base::MessageLoop> message_loop_; |
| scoped_ptr<gfx::SurfaceFactoryOzone> surface_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceOzoneTest); |
| }; |
| |
| SoftwareOutputDeviceOzoneTest::SoftwareOutputDeviceOzoneTest() { |
| CHECK(gfx::InitializeGLBindings(gfx::kGLImplementationOSMesaGL)); |
| message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_UI)); |
| } |
| |
| SoftwareOutputDeviceOzoneTest::~SoftwareOutputDeviceOzoneTest() { |
| } |
| |
| void SoftwareOutputDeviceOzoneTest::SetUp() { |
| ui::InitializeContextFactoryForTests(false); |
| ui::Compositor::Initialize(); |
| |
| surface_factory_.reset(new MockSurfaceFactoryOzone()); |
| gfx::SurfaceFactoryOzone::SetInstance(surface_factory_.get()); |
| |
| const gfx::Size size(500, 400); |
| compositor_.reset(new ui::Compositor(gfx::SurfaceFactoryOzone::GetInstance() |
| ->GetAcceleratedWidget())); |
| compositor_->SetScaleAndSize(1.0f, size); |
| |
| output_device_.reset(new content::SoftwareOutputDeviceOzone( |
| compositor_.get())); |
| output_device_->Resize(size); |
| } |
| |
| void SoftwareOutputDeviceOzoneTest::TearDown() { |
| output_device_.reset(); |
| compositor_.reset(); |
| surface_factory_.reset(); |
| ui::TerminateContextFactoryForTests(); |
| ui::Compositor::Terminate(); |
| } |
| |
| TEST_F(SoftwareOutputDeviceOzoneTest, CheckClipAfterBeginPaint) { |
| gfx::Rect damage(10, 10, 100, 100); |
| SkCanvas* canvas = output_device_->BeginPaint(damage); |
| |
| SkIRect sk_bounds; |
| canvas->getClipDeviceBounds(&sk_bounds); |
| |
| EXPECT_EQ(damage.ToString(), gfx::SkIRectToRect(sk_bounds).ToString()); |
| } |
| |
| TEST_F(SoftwareOutputDeviceOzoneTest, CheckClipAfterSecondBeginPaint) { |
| gfx::Rect damage(10, 10, 100, 100); |
| SkCanvas* canvas = output_device_->BeginPaint(damage); |
| |
| cc::SoftwareFrameData frame; |
| output_device_->EndPaint(&frame); |
| |
| damage = gfx::Rect(100, 100, 100, 100); |
| canvas = output_device_->BeginPaint(damage); |
| SkIRect sk_bounds; |
| canvas->getClipDeviceBounds(&sk_bounds); |
| |
| EXPECT_EQ(damage.ToString(), gfx::SkIRectToRect(sk_bounds).ToString()); |
| } |
| |
| TEST_F(SoftwareOutputDeviceOzoneTest, CheckCorrectResizeBehavior) { |
| gfx::Rect damage(0, 0, 100, 100); |
| gfx::Size size(200, 100); |
| // Reduce size. |
| output_device_->Resize(size); |
| |
| SkCanvas* canvas = output_device_->BeginPaint(damage); |
| gfx::Size canvas_size(canvas->getDeviceSize().width(), |
| canvas->getDeviceSize().height()); |
| EXPECT_EQ(size.ToString(), canvas_size.ToString()); |
| |
| size.SetSize(1000, 500); |
| // Increase size. |
| output_device_->Resize(size); |
| |
| canvas = output_device_->BeginPaint(damage); |
| canvas_size.SetSize(canvas->getDeviceSize().width(), |
| canvas->getDeviceSize().height()); |
| EXPECT_EQ(size.ToString(), canvas_size.ToString()); |
| |
| } |
| |
| TEST_F(SoftwareOutputDeviceOzoneTest, CheckCopyToBitmap) { |
| const gfx::Rect area(6, 4); |
| output_device_->Resize(area.size()); |
| SkCanvas* canvas = output_device_->BeginPaint(area); |
| |
| // Clear the background to black. |
| canvas->drawColor(SK_ColorBLACK); |
| |
| cc::SoftwareFrameData frame; |
| output_device_->EndPaint(&frame); |
| |
| // Draw a white rectangle. |
| gfx::Rect damage(area.width() / 2, area.height() / 2); |
| canvas = output_device_->BeginPaint(damage); |
| |
| canvas->drawColor(SK_ColorWHITE); |
| |
| output_device_->EndPaint(&frame); |
| |
| SkBitmap bitmap; |
| output_device_->CopyToBitmap(area, &bitmap); |
| |
| SkAutoLockPixels pixel_lock(bitmap); |
| // Check that the copied bitmap contains the same pixel values as what we |
| // painted. |
| for (int i = 0; i < area.height(); ++i) { |
| for (int j = 0; j < area.width(); ++j) { |
| if (j < damage.width() && i < damage.height()) |
| EXPECT_EQ(SK_ColorWHITE, bitmap.getColor(j, i)); |
| else |
| EXPECT_EQ(SK_ColorBLACK, bitmap.getColor(j, i)); |
| } |
| } |
| } |