summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authordnicoara@chromium.org <dnicoara@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-23 19:19:54 +0000
committerdnicoara@chromium.org <dnicoara@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-23 19:19:54 +0000
commitf6a5261539900d7fb66c05623e091fad88c8b905 (patch)
tree847e8e8ed23cdeaa1859d351f7f7ef70de5f48dd /content
parentd513eb6c79e2a529160ef1d14475b73a1eaa23af (diff)
downloadchromium_src-f6a5261539900d7fb66c05623e091fad88c8b905.zip
chromium_src-f6a5261539900d7fb66c05623e091fad88c8b905.tar.gz
chromium_src-f6a5261539900d7fb66c05623e091fad88c8b905.tar.bz2
SoftwareOutputDevice implementation using an OZONE software renderer as the backend.
SOD's expectation is that Ozone provides a SkCanvas as the accelerated widget. BUG= Review URL: https://codereview.chromium.org/23862004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@230488 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/aura/gpu_process_transport_factory.cc5
-rw-r--r--content/browser/aura/software_output_device_ozone.cc69
-rw-r--r--content/browser/aura/software_output_device_ozone.h36
-rw-r--r--content/browser/aura/software_output_device_ozone_unittest.cc189
-rw-r--r--content/content_browser.gypi2
-rw-r--r--content/content_tests.gypi1
6 files changed, 302 insertions, 0 deletions
diff --git a/content/browser/aura/gpu_process_transport_factory.cc b/content/browser/aura/gpu_process_transport_factory.cc
index 64ba33d..12bfd8c 100644
--- a/content/browser/aura/gpu_process_transport_factory.cc
+++ b/content/browser/aura/gpu_process_transport_factory.cc
@@ -36,6 +36,8 @@
#if defined(OS_WIN)
#include "content/browser/aura/software_output_device_win.h"
#include "ui/surface/accelerated_surface_win.h"
+#elif defined(USE_OZONE)
+#include "content/browser/aura/software_output_device_ozone.h"
#elif defined(USE_X11)
#include "content/browser/aura/software_output_device_x11.h"
#endif
@@ -205,6 +207,9 @@ scoped_ptr<cc::SoftwareOutputDevice> CreateSoftwareOutputDevice(
#if defined(OS_WIN)
return scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareOutputDeviceWin(
compositor));
+#elif defined(USE_OZONE)
+ return scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareOutputDeviceOzone(
+ compositor));
#elif defined(USE_X11)
return scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareOutputDeviceX11(
compositor));
diff --git a/content/browser/aura/software_output_device_ozone.cc b/content/browser/aura/software_output_device_ozone.cc
new file mode 100644
index 0000000..c704fed
--- /dev/null
+++ b/content/browser/aura/software_output_device_ozone.cc
@@ -0,0 +1,69 @@
+// 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 "content/browser/aura/software_output_device_ozone.h"
+#include "third_party/skia/include/core/SkBitmapDevice.h"
+#include "third_party/skia/include/core/SkDevice.h"
+#include "ui/compositor/compositor.h"
+#include "ui/gfx/ozone/surface_factory_ozone.h"
+#include "ui/gfx/skia_util.h"
+
+namespace content {
+
+SoftwareOutputDeviceOzone::SoftwareOutputDeviceOzone(
+ ui::Compositor* compositor) : compositor_(compositor) {
+ if (gfx::SurfaceFactoryOzone::GetInstance()->InitializeHardware() !=
+ gfx::SurfaceFactoryOzone::INITIALIZED)
+ LOG(FATAL) << "Failed to initialize hardware in OZONE";
+}
+
+SoftwareOutputDeviceOzone::~SoftwareOutputDeviceOzone() {
+}
+
+void SoftwareOutputDeviceOzone::Resize(gfx::Size viewport_size) {
+ if (viewport_size_ == viewport_size)
+ return;
+
+ viewport_size_ = viewport_size;
+ gfx::Rect bounds(viewport_size_);
+
+ gfx::SurfaceFactoryOzone* factory = gfx::SurfaceFactoryOzone::GetInstance();
+ factory->AttemptToResizeAcceleratedWidget(compositor_->widget(),
+ bounds);
+ gfx::AcceleratedWidget realized_widget = factory->RealizeAcceleratedWidget(
+ compositor_->widget());
+
+ if (realized_widget == gfx::kNullAcceleratedWidget)
+ LOG(FATAL) << "Failed to get a realized AcceleratedWidget";
+
+ canvas_ = skia::SharePtr(factory->GetCanvasForWidget(realized_widget));
+ device_ = skia::SharePtr(canvas_->getDevice());
+}
+
+SkCanvas* SoftwareOutputDeviceOzone::BeginPaint(gfx::Rect damage_rect) {
+ DCHECK(gfx::Rect(viewport_size_).Contains(damage_rect));
+
+ canvas_->clipRect(gfx::RectToSkRect(damage_rect), SkRegion::kReplace_Op);
+ // Save the current state so we can restore once we're done drawing. This is
+ // saved after the clip since we want to keep the clip information after we're
+ // done drawing such that OZONE knows what was updated.
+ canvas_->save();
+
+ return SoftwareOutputDevice::BeginPaint(damage_rect);
+}
+
+void SoftwareOutputDeviceOzone::EndPaint(cc::SoftwareFrameData* frame_data) {
+ SoftwareOutputDevice::EndPaint(frame_data);
+
+ canvas_->restore();
+
+ if (damage_rect_.IsEmpty())
+ return;
+
+ bool scheduled = gfx::SurfaceFactoryOzone::GetInstance()->SchedulePageFlip(
+ compositor_->widget());
+ DCHECK(scheduled) << "Failed to schedule pageflip";
+}
+
+} // namespace content
diff --git a/content/browser/aura/software_output_device_ozone.h b/content/browser/aura/software_output_device_ozone.h
new file mode 100644
index 0000000..cee91f8
--- /dev/null
+++ b/content/browser/aura/software_output_device_ozone.h
@@ -0,0 +1,36 @@
+// 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.
+
+#ifndef CONTENT_BROWSER_AURA_SOFTWARE_OUTPUT_DEVICE_OZONE_H_
+#define CONTENT_BROWSER_AURA_SOFTWARE_OUTPUT_DEVICE_OZONE_H_
+
+#include "cc/output/software_output_device.h"
+
+namespace ui {
+class Compositor;
+}
+
+namespace content {
+
+// Ozone implementation which relies on software rendering. Ozone will present
+// an accelerated widget as a SkCanvas. SoftwareOutputDevice will then use the
+// Ozone provided canvas to draw.
+class SoftwareOutputDeviceOzone : public cc::SoftwareOutputDevice {
+ public:
+ explicit SoftwareOutputDeviceOzone(ui::Compositor* compositor);
+ virtual ~SoftwareOutputDeviceOzone();
+
+ virtual void Resize(gfx::Size viewport_size) OVERRIDE;
+ virtual SkCanvas* BeginPaint(gfx::Rect damage_rect) OVERRIDE;
+ virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE;
+
+ private:
+ ui::Compositor* compositor_;
+
+ DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceOzone);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_AURA_SOFTWARE_OUTPUT_DEVICE_OZONE_H_
diff --git a/content/browser/aura/software_output_device_ozone_unittest.cc b/content/browser/aura/software_output_device_ozone_unittest.cc
new file mode 100644
index 0000000..552116e
--- /dev/null
+++ b/content/browser/aura/software_output_device_ozone_unittest.cc
@@ -0,0 +1,189 @@
+// 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/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::Compositor::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::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));
+ }
+ }
+}
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index a1bf021..a064be2 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -308,6 +308,8 @@
'browser/aura/resize_lock.h',
'browser/aura/software_browser_compositor_output_surface.cc',
'browser/aura/software_browser_compositor_output_surface.h',
+ 'browser/aura/software_output_device_ozone.cc',
+ 'browser/aura/software_output_device_ozone.h',
'browser/aura/software_output_device_win.cc',
'browser/aura/software_output_device_win.h',
'browser/aura/software_output_device_x11.cc',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 69c7f1c..45d5b50 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -325,6 +325,7 @@
'browser/accessibility/browser_accessibility_manager_unittest.cc',
'browser/accessibility/browser_accessibility_win_unittest.cc',
'browser/appcache/chrome_appcache_service_unittest.cc',
+ 'browser/aura/software_output_device_ozone_unittest.cc',
'browser/browser_thread_unittest.cc',
'browser/browser_url_handler_impl_unittest.cc',
'browser/byte_stream_unittest.cc',