summaryrefslogtreecommitdiffstats
path: root/ui/ozone
diff options
context:
space:
mode:
authordnicoara@chromium.org <dnicoara@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-29 17:22:50 +0000
committerdnicoara@chromium.org <dnicoara@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-29 17:22:50 +0000
commit26ce20d5512fadbcfeb3462656da42ce42b67803 (patch)
treed2bf4c1a80f81e722d06c37b03772aefe9bbbdfc /ui/ozone
parent54743a5071e673a394501c3da0f3de7409cf3891 (diff)
downloadchromium_src-26ce20d5512fadbcfeb3462656da42ce42b67803.zip
chromium_src-26ce20d5512fadbcfeb3462656da42ce42b67803.tar.gz
chromium_src-26ce20d5512fadbcfeb3462656da42ce42b67803.tar.bz2
GBM Ozone implementation
Adding an accelerated platform for the X11-less build. This uses GBM (EGL_MESA_platform_gbm) as the backing Mesa platform. BUG=377497 Review URL: https://codereview.chromium.org/106633002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@273509 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/ozone')
-rw-r--r--ui/ozone/ozone.gyp7
-rw-r--r--ui/ozone/ozone_unittests.gypi2
-rw-r--r--ui/ozone/platform/dri/dri.gypi3
-rw-r--r--ui/ozone/platform/dri/dri_surface.cc4
-rw-r--r--ui/ozone/platform/dri/dri_surface.h126
-rw-r--r--ui/ozone/platform/dri/dri_surface_factory.cc3
-rw-r--r--ui/ozone/platform/dri/dri_surface_factory.h2
-rw-r--r--ui/ozone/platform/dri/dri_surface_factory_unittest.cc22
-rw-r--r--ui/ozone/platform/dri/dri_surface_unittest.cc2
-rw-r--r--ui/ozone/platform/dri/gbm.gypi41
-rw-r--r--ui/ozone/platform/dri/gbm_surface.cc206
-rw-r--r--ui/ozone/platform/dri/gbm_surface.h75
-rw-r--r--ui/ozone/platform/dri/gbm_surface_factory.cc153
-rw-r--r--ui/ozone/platform/dri/gbm_surface_factory.h39
-rw-r--r--ui/ozone/platform/dri/hardware_display_controller.cc14
-rw-r--r--ui/ozone/platform/dri/hardware_display_controller.h10
-rw-r--r--ui/ozone/platform/dri/hardware_display_controller_unittest.cc8
-rw-r--r--ui/ozone/platform/dri/ozone_platform_dri.cc22
-rw-r--r--ui/ozone/platform/dri/ozone_platform_gbm.cc114
-rw-r--r--ui/ozone/platform/dri/ozone_platform_gbm.h17
-rw-r--r--ui/ozone/platform/dri/scanout_surface.h84
-rw-r--r--ui/ozone/platform/dri/screen_manager.cc15
-rw-r--r--ui/ozone/platform/dri/screen_manager.h6
-rw-r--r--ui/ozone/platform/dri/screen_manager_unittest.cc14
-rw-r--r--ui/ozone/platform/dri/test/mock_surface_generator.cc18
-rw-r--r--ui/ozone/platform/dri/test/mock_surface_generator.h40
26 files changed, 878 insertions, 169 deletions
diff --git a/ui/ozone/ozone.gyp b/ui/ozone/ozone.gyp
index 9261add..ca937bc 100644
--- a/ui/ozone/ozone.gyp
+++ b/ui/ozone/ozone.gyp
@@ -92,7 +92,7 @@
'platform/caca/caca.gypi',
],
}],
- ['<(ozone_platform_dri) == 1', {
+ ['<(ozone_platform_dri) == 1 or <(ozone_platform_gbm) == 1', {
'includes': [
'platform/dri/dri.gypi',
],
@@ -102,6 +102,11 @@
'platform/egltest/egltest.gypi',
],
}],
+ ['<(ozone_platform_gbm) == 1', {
+ 'includes': [
+ 'platform/dri/gbm.gypi',
+ ],
+ }],
['<(ozone_platform_test) == 1', {
'includes': [
'platform/test/test.gypi',
diff --git a/ui/ozone/ozone_unittests.gypi b/ui/ozone/ozone_unittests.gypi
index f4469f3..b57f47e 100644
--- a/ui/ozone/ozone_unittests.gypi
+++ b/ui/ozone/ozone_unittests.gypi
@@ -12,6 +12,8 @@
'platform/dri/test/mock_dri_surface.h',
'platform/dri/test/mock_dri_wrapper.cc',
'platform/dri/test/mock_dri_wrapper.h',
+ 'platform/dri/test/mock_surface_generator.cc',
+ 'platform/dri/test/mock_surface_generator.h',
],
'conditions': [
['ozone_platform_dri == 1', {
diff --git a/ui/ozone/platform/dri/dri.gypi b/ui/ozone/platform/dri/dri.gypi
index 9157a9d..2bbcd47 100644
--- a/ui/ozone/platform/dri/dri.gypi
+++ b/ui/ozone/platform/dri/dri.gypi
@@ -8,7 +8,7 @@
'ozone_platform_dri',
],
'internal_ozone_platforms': [
- 'dri'
+ 'dri',
],
},
'targets': [
@@ -57,6 +57,7 @@
'ozone_platform_dri.h',
'screen_manager.cc',
'screen_manager.h',
+ 'scanout_surface.h',
],
},
],
diff --git a/ui/ozone/platform/dri/dri_surface.cc b/ui/ozone/platform/dri/dri_surface.cc
index 6b296cc2..d6b4f59 100644
--- a/ui/ozone/platform/dri/dri_surface.cc
+++ b/ui/ozone/platform/dri/dri_surface.cc
@@ -66,6 +66,10 @@ void DriSurface::SwapBuffers() {
front_buffer_ ^= 1;
}
+gfx::Size DriSurface::Size() const {
+ return size_;
+}
+
SkCanvas* DriSurface::GetDrawableForWidget() {
CHECK(backbuffer());
return backbuffer()->canvas();
diff --git a/ui/ozone/platform/dri/dri_surface.h b/ui/ozone/platform/dri/dri_surface.h
index 2fde4d4..2abae45 100644
--- a/ui/ozone/platform/dri/dri_surface.h
+++ b/ui/ozone/platform/dri/dri_surface.h
@@ -10,6 +10,7 @@
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/skia_util.h"
#include "ui/ozone/ozone_export.h"
+#include "ui/ozone/platform/dri/scanout_surface.h"
class SkCanvas;
@@ -18,129 +19,22 @@ namespace ui {
class DriBuffer;
class DriWrapper;
-// DriSurface is used to represent a surface that can be scanned out
-// to a monitor. It will store the internal state associated with the drawing
-// surface associated with it. DriSurface also performs all the needed
-// operations to initialize and update the drawing surface.
-//
-// The implementation uses dumb buffers, which is used for software rendering.
-// The intent is to have one DriSurface implementation for a
-// HardwareDisplayController.
-//
-// DoubleBufferedSurface is intended to be the software analog to
-// EGLNativeSurface while DriSurface is intended to provide the glue
-// necessary to initialize and display the surface to the screen.
-//
-// The typical usage pattern is:
-// -----------------------------------------------------------------------------
-// HardwareDisplayController controller;
-// // Initialize controller
-//
-// DriSurface* surface = new DriSurface(dri_wrapper, size);
-// surface.Initialize();
-// controller.BindSurfaceToController(surface);
-//
-// while (true) {
-// SkCanvas* canvas = surface->GetDrawableForWidget();
-// DrawStuff(canvas);
-// controller.SchedulePageFlip();
-//
-// Wait for page flip event. The DRM page flip handler will call
-// surface.SwapBuffers();
-// }
-//
-// delete surface;
-// -----------------------------------------------------------------------------
-// In the above example the wait consists of reading a DRM pageflip event from
-// the graphics card file descriptor. This is done by calling |drmHandleEvent|,
-// which will read and process the event. |drmHandleEvent| will call a callback
-// registered by |SchedulePageFlip| which will update the internal state.
-//
-// |SchedulePageFlip| can also be used to limit drawing to the screen's vsync
-// since page flips only happen on vsync. In a threaded environment a message
-// loop would listen on the graphics card file descriptor for an event and
-// |drmHandleEvent| would be called from the message loop. The event handler
-// would also be responsible for updating the renderer's state and signal that
-// it is OK to start drawing the next frame.
-//
-// The following example will illustrate the system state transitions in one
-// iteration of the above loop.
-//
-// 1. Both buffers contain the same image with b[0] being the front buffer
-// (star will represent the frontbuffer).
-// ------- -------
-// | | | |
-// | | | |
-// | | | |
-// | | | |
-// ------- -------
-// b[0]* b[1]
-//
-// 2. Call |GetBackbuffer| to get a SkCanvas wrapper for the backbuffer and draw
-// to it.
-// ------- -------
-// | | | |
-// | | | d |
-// | | | |
-// | | | |
-// ------- -------
-// b[0]* b[1]
-//
-// 3. Call |SchedulePageFlip| to display the backbuffer. At this point we can't
-// modify b[0] because it is the frontbuffer and we can't modify b[1] since it
-// has been scheduled for pageflip. If we do draw in b[1] it is possible that
-// the pageflip and draw happen at the same time and we could get tearing.
-//
-// 4. The pageflip callback is called which will call |SwapSurfaces|. Before
-// |SwapSurfaces| is called the state is as following from the hardware's
-// perspective:
-// ------- -------
-// | | | |
-// | | | d |
-// | | | |
-// | | | |
-// ------- -------
-// b[0] b[1]*
-//
-// 5. |SwapSurfaces| will update out internal reference to the front buffer and
-// synchronize the damaged area such that both buffers are identical. The
-// damaged area is used from the SkCanvas clip.
-// ------- -------
-// | | | |
-// | d | | d |
-// | | | |
-// | | | |
-// ------- -------
-// b[0] b[1]*
-//
-// The synchronization consists of copying the damaged area from the frontbuffer
-// to the backbuffer.
-//
-// At this point we're back to step 1 and can start a new draw iteration.
-class OZONE_EXPORT DriSurface {
+// An implementation of ScanoutSurface which uses dumb buffers (used for
+// software rendering).
+class OZONE_EXPORT DriSurface : public ScanoutSurface {
public:
DriSurface(DriWrapper* dri, const gfx::Size& size);
virtual ~DriSurface();
- // Used to allocate all necessary buffers for this surface. If the
- // initialization succeeds, the device is ready to be used for drawing
- // operations.
- // Returns true if the initialization is successful, false otherwise.
- bool Initialize();
-
- // Returns the ID of the current backbuffer.
- uint32_t GetFramebufferId() const;
-
- // Returns the handle for the current backbuffer.
- uint32_t GetHandle() const;
-
- // Synchronizes and swaps the back buffer with the front buffer.
- void SwapBuffers();
-
// Get a Skia canvas for a backbuffer.
SkCanvas* GetDrawableForWidget();
- const gfx::Size& size() const { return size_; }
+ // ScanoutSurface:
+ virtual bool Initialize() OVERRIDE;
+ virtual uint32_t GetFramebufferId() const OVERRIDE;
+ virtual uint32_t GetHandle() const OVERRIDE;
+ virtual void SwapBuffers() OVERRIDE;
+ virtual gfx::Size Size() const OVERRIDE;
private:
DriBuffer* frontbuffer() const { return bitmaps_[front_buffer_].get(); }
diff --git a/ui/ozone/platform/dri/dri_surface_factory.cc b/ui/ozone/platform/dri/dri_surface_factory.cc
index 93fc4b4..71cb4ce 100644
--- a/ui/ozone/platform/dri/dri_surface_factory.cc
+++ b/ui/ozone/platform/dri/dri_surface_factory.cc
@@ -96,7 +96,8 @@ scoped_ptr<gfx::VSyncProvider> DriSurfaceAdapter::CreateVSyncProvider() {
}
void DriSurfaceAdapter::UpdateNativeSurface(const gfx::Rect& damage) {
- SkCanvas* canvas = controller_->surface()->GetDrawableForWidget();
+ SkCanvas* canvas = static_cast<DriSurface*>(controller_->surface())
+ ->GetDrawableForWidget();
// The DriSurface is double buffered, so the current back buffer is
// missing the previous update. Expand damage region.
diff --git a/ui/ozone/platform/dri/dri_surface_factory.h b/ui/ozone/platform/dri/dri_surface_factory.h
index b2ba52c..f26b9ed 100644
--- a/ui/ozone/platform/dri/dri_surface_factory.h
+++ b/ui/ozone/platform/dri/dri_surface_factory.h
@@ -59,7 +59,7 @@ class OZONE_EXPORT DriSurfaceFactory : public gfx::SurfaceFactoryOzone {
void UnsetHardwareCursor(gfx::AcceleratedWidget window);
- private:
+ protected:
// Draw the last set cursor & update the cursor plane.
void ResetCursor(gfx::AcceleratedWidget w);
diff --git a/ui/ozone/platform/dri/dri_surface_factory_unittest.cc b/ui/ozone/platform/dri/dri_surface_factory_unittest.cc
index 1622e7e..4cdd1bf 100644
--- a/ui/ozone/platform/dri/dri_surface_factory_unittest.cc
+++ b/ui/ozone/platform/dri/dri_surface_factory_unittest.cc
@@ -18,6 +18,7 @@
#include "ui/ozone/platform/dri/screen_manager.h"
#include "ui/ozone/platform/dri/test/mock_dri_surface.h"
#include "ui/ozone/platform/dri/test/mock_dri_wrapper.h"
+#include "ui/ozone/platform/dri/test/mock_surface_generator.h"
namespace {
@@ -53,25 +54,17 @@ class MockDriSurfaceFactory : public ui::DriSurfaceFactory {
class MockScreenManager : public ui::ScreenManager {
public:
- MockScreenManager(ui::DriWrapper* dri)
- : ScreenManager(dri),
+ MockScreenManager(ui::DriWrapper* dri,
+ ui::ScanoutSurfaceGenerator* surface_generator)
+ : ScreenManager(dri, surface_generator),
dri_(dri) {}
virtual ~MockScreenManager() {}
- const std::vector<ui::MockDriSurface*>& get_surfaces() const {
- return surfaces_;
- }
-
// Normally we'd use DRM to figure out the controller configuration. But we
// can't use DRM in unit tests, so we just create a fake configuration.
virtual void ForceInitializationOfPrimaryDisplay() OVERRIDE {
ConfigureDisplayController(1, 2, kDefaultMode);
}
- virtual ui::DriSurface* CreateSurface(const gfx::Size& size) OVERRIDE {
- ui::MockDriSurface* surface = new ui::MockDriSurface(dri_, size);
- surfaces_.push_back(surface);
- return surface;
- }
private:
ui::DriWrapper* dri_; // Not owned.
@@ -91,6 +84,7 @@ class DriSurfaceFactoryTest : public testing::Test {
protected:
scoped_ptr<base::MessageLoop> message_loop_;
scoped_ptr<ui::MockDriWrapper> dri_;
+ scoped_ptr<ui::MockSurfaceGenerator> surface_generator_;
scoped_ptr<MockScreenManager> screen_manager_;
scoped_ptr<MockDriSurfaceFactory> factory_;
@@ -101,7 +95,9 @@ class DriSurfaceFactoryTest : public testing::Test {
void DriSurfaceFactoryTest::SetUp() {
message_loop_.reset(new base::MessageLoopForUI);
dri_.reset(new ui::MockDriWrapper(3));
- screen_manager_.reset(new MockScreenManager(dri_.get()));
+ surface_generator_.reset(new ui::MockSurfaceGenerator(dri_.get()));
+ screen_manager_.reset(new MockScreenManager(dri_.get(),
+ surface_generator_.get()));
factory_.reset(new MockDriSurfaceFactory(dri_.get(), screen_manager_.get()));
}
@@ -147,7 +143,7 @@ TEST_F(DriSurfaceFactoryTest, CheckNativeSurfaceContents) {
gfx::Rect(0, 0, kDefaultMode.hdisplay / 2, kDefaultMode.vdisplay / 2));
const std::vector<ui::DriBuffer*>& bitmaps =
- screen_manager_->get_surfaces()[0]->bitmaps();
+ surface_generator_->surfaces()[0]->bitmaps();
SkBitmap image;
bitmaps[1]->canvas()->readPixels(&image, 0, 0);
diff --git a/ui/ozone/platform/dri/dri_surface_unittest.cc b/ui/ozone/platform/dri/dri_surface_unittest.cc
index af47a64..397e54f 100644
--- a/ui/ozone/platform/dri/dri_surface_unittest.cc
+++ b/ui/ozone/platform/dri/dri_surface_unittest.cc
@@ -61,7 +61,7 @@ TEST_F(DriSurfaceTest, SuccessfulInitialization) {
TEST_F(DriSurfaceTest, CheckFBIDOnSwap) {
EXPECT_TRUE(surface_->Initialize());
- controller_->BindSurfaceToController(surface_.PassAs<ui::DriSurface>(),
+ controller_->BindSurfaceToController(surface_.PassAs<ui::ScanoutSurface>(),
kDefaultMode);
// Check that the framebuffer ID is correct.
diff --git a/ui/ozone/platform/dri/gbm.gypi b/ui/ozone/platform/dri/gbm.gypi
new file mode 100644
index 0000000..a3c5555
--- /dev/null
+++ b/ui/ozone/platform/dri/gbm.gypi
@@ -0,0 +1,41 @@
+# Copyright 2014 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.
+
+{
+ 'variables': {
+ 'internal_ozone_platform_deps': [
+ 'ozone_platform_gbm',
+ ],
+ 'internal_ozone_platforms': [
+ 'gbm',
+ ],
+ },
+ 'targets': [
+ {
+ 'target_name': 'ozone_platform_gbm',
+ 'type': 'static_library',
+ 'dependencies': [
+ '../../base/base.gyp:base',
+ '../../build/linux/system.gyp:dridrm',
+ '../../build/linux/system.gyp:gbm',
+ '../../skia/skia.gyp:skia',
+ '../base/ui_base.gyp:ui_base',
+ '../events/events.gyp:events',
+ '../events/ozone/events_ozone.gyp:events_ozone',
+ '../gfx/gfx.gyp:gfx',
+ ],
+ 'defines': [
+ 'OZONE_IMPLEMENTATION',
+ ],
+ 'sources': [
+ 'gbm_surface.cc',
+ 'gbm_surface.h',
+ 'gbm_surface_factory.cc',
+ 'gbm_surface_factory.h',
+ 'ozone_platform_gbm.cc',
+ 'ozone_platform_gbm.h',
+ ],
+ },
+ ],
+}
diff --git a/ui/ozone/platform/dri/gbm_surface.cc b/ui/ozone/platform/dri/gbm_surface.cc
new file mode 100644
index 0000000..ce25072
--- /dev/null
+++ b/ui/ozone/platform/dri/gbm_surface.cc
@@ -0,0 +1,206 @@
+// Copyright 2014 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 "ui/ozone/platform/dri/gbm_surface.h"
+
+#include <gbm.h>
+
+#include "base/logging.h"
+#include "third_party/skia/include/core/SkImageInfo.h"
+#include "ui/ozone/platform/dri/dri_buffer.h"
+#include "ui/ozone/platform/dri/dri_wrapper.h"
+#include "ui/ozone/platform/dri/gbm_surface.h"
+#include "ui/ozone/platform/dri/hardware_display_controller.h"
+
+namespace ui {
+
+namespace {
+
+// Pixel configuration for the current buffer format.
+// TODO(dnicoara) These will need to change once we'll query the hardware for
+// supported configurations.
+const uint8_t kColorDepth = 24;
+const uint8_t kPixelDepth = 32;
+
+class BufferData {
+ public:
+ // When we create the BufferData we need to register the buffer. Once
+ // successfully registered, the |framebuffer_| field will hold the ID of the
+ // buffer. The controller will use this ID when scanning out the buffer. On
+ // creation we will also associate the BufferData with the buffer.
+ static BufferData* CreateData(DriWrapper* dri, gbm_bo* buffer);
+
+ // Callback used by GBM to destory the BufferData associated with a buffer.
+ static void Destroy(gbm_bo* buffer, void* data);
+
+ // Returns the BufferData associated with |buffer|. NULL if no data is
+ // associated.
+ static BufferData* GetData(gbm_bo* buffer);
+
+ uint32_t framebuffer() const { return framebuffer_; }
+ uint32_t handle() const { return handle_; }
+
+ private:
+ BufferData(DriWrapper* dri, gbm_bo* buffer);
+ ~BufferData();
+
+ DriWrapper* dri_;
+
+ uint32_t handle_;
+
+ // ID provided by the controller when the buffer is registered. This ID is
+ // used when scanning out the buffer.
+ uint32_t framebuffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(BufferData);
+};
+
+BufferData::BufferData(DriWrapper* dri, gbm_bo* buffer)
+ : dri_(dri),
+ handle_(gbm_bo_get_handle(buffer).u32),
+ framebuffer_(0) {
+ // Register the buffer with the controller. This will allow us to scan out the
+ // buffer once we're done drawing into it. If we can't register the buffer
+ // then there's no point in having BufferData associated with it.
+ if (!dri_->AddFramebuffer(gbm_bo_get_width(buffer),
+ gbm_bo_get_height(buffer),
+ kColorDepth,
+ kPixelDepth,
+ gbm_bo_get_stride(buffer),
+ handle_,
+ &framebuffer_)) {
+ LOG(ERROR) << "Failed to register buffer";
+ }
+}
+
+BufferData::~BufferData() {
+ if (framebuffer_)
+ dri_->RemoveFramebuffer(framebuffer_);
+}
+
+// static
+BufferData* BufferData::CreateData(DriWrapper* dri,
+ gbm_bo* buffer) {
+ BufferData* data = new BufferData(dri, buffer);
+ if (!data->framebuffer()) {
+ delete data;
+ return NULL;
+ }
+
+ // GBM can destroy the buffers at any time as long as they aren't locked. This
+ // sets a callback such that we can clean up all our state when GBM destroys
+ // the buffer.
+ gbm_bo_set_user_data(buffer, data, BufferData::Destroy);
+
+ return data;
+}
+
+// static
+void BufferData::Destroy(gbm_bo* buffer, void* data) {
+ BufferData* bd = static_cast<BufferData*>(data);
+ delete bd;
+}
+
+// static
+BufferData* BufferData::GetData(gbm_bo* buffer) {
+ return static_cast<BufferData*>(gbm_bo_get_user_data(buffer));
+}
+
+} // namespace
+
+GbmSurface::GbmSurface(gbm_device* device,
+ DriWrapper* dri,
+ const gfx::Size& size)
+ : gbm_device_(device),
+ dri_(dri),
+ size_(size),
+ native_surface_(NULL),
+ buffers_(),
+ front_buffer_(0) {
+ for (size_t i = 0; i < arraysize(buffers_); ++i)
+ buffers_[i] = NULL;
+}
+
+GbmSurface::~GbmSurface() {
+ for (size_t i = 0; i < arraysize(buffers_); ++i) {
+ if (buffers_[i]) {
+ gbm_surface_release_buffer(native_surface_, buffers_[i]);
+ }
+ }
+
+ if (native_surface_)
+ gbm_surface_destroy(native_surface_);
+}
+
+bool GbmSurface::Initialize() {
+ // TODO(dnicoara) Check underlying system support for pixel format.
+ native_surface_ = gbm_surface_create(
+ gbm_device_,
+ size_.width(),
+ size_.height(),
+ GBM_BO_FORMAT_XRGB8888,
+ GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
+
+ if (!native_surface_)
+ return false;
+
+ dumb_buffer_.reset(new DriBuffer(dri_));
+ if (!dumb_buffer_->Initialize(SkImageInfo::MakeN32Premul(size_.width(),
+ size_.height())))
+ return false;
+
+ return true;
+}
+
+uint32_t GbmSurface::GetFramebufferId() const {
+ if (!buffers_[front_buffer_ ^ 1])
+ return dumb_buffer_->framebuffer();
+
+ BufferData* data = BufferData::GetData(buffers_[front_buffer_ ^ 1]);
+ CHECK(data);
+ return data->framebuffer();
+}
+
+uint32_t GbmSurface::GetHandle() const {
+ if (!buffers_[front_buffer_ ^ 1])
+ return dumb_buffer_->handle();
+
+ BufferData* data = BufferData::GetData(buffers_[front_buffer_ ^ 1]);
+ CHECK(data);
+ return data->handle();
+}
+
+gfx::Size GbmSurface::Size() const {
+ return size_;
+}
+
+void GbmSurface::SwapBuffers() {
+ // If there was a frontbuffer, is no longer active. Release it back to GBM.
+ if (buffers_[front_buffer_])
+ gbm_surface_release_buffer(native_surface_, buffers_[front_buffer_]);
+
+ // Update the index to the frontbuffer.
+ front_buffer_ ^= 1;
+ // We've just released it. Since GBM doesn't guarantee we'll get the same
+ // buffer back, we set it to NULL so we don't keep track of objects that may
+ // have been destroyed.
+ buffers_[front_buffer_ ^ 1] = NULL;
+}
+
+void GbmSurface::LockCurrentDrawable() {
+ CHECK(native_surface_);
+ // Lock the buffer we want to display.
+ buffers_[front_buffer_ ^ 1] = gbm_surface_lock_front_buffer(native_surface_);
+
+ BufferData* data = BufferData::GetData(buffers_[front_buffer_ ^ 1]);
+ // If it is a new buffer, it won't have any data associated with it. So we
+ // create it. On creation it will associate itself with the buffer and
+ // register the buffer.
+ if (!data) {
+ data = BufferData::CreateData(dri_, buffers_[front_buffer_ ^ 1]);
+ DCHECK(data) << "Failed to associate the buffer with the controller";
+ }
+}
+
+} // namespace ui
diff --git a/ui/ozone/platform/dri/gbm_surface.h b/ui/ozone/platform/dri/gbm_surface.h
new file mode 100644
index 0000000..8a33ab5
--- /dev/null
+++ b/ui/ozone/platform/dri/gbm_surface.h
@@ -0,0 +1,75 @@
+// Copyright 2014 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 UI_OZONE_PLATFORM_DRI_GBM_SURFACE_H_
+#define UI_OZONE_PLATFORM_DRI_GBM_SURFACE_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/ozone/platform/dri/scanout_surface.h"
+
+struct gbm_bo;
+struct gbm_device;
+struct gbm_surface;
+
+namespace ui {
+
+class DriBuffer;
+class DriWrapper;
+
+// Implement the ScanoutSurface interface on top of GBM (Generic Buffer
+// Manager). GBM provides generic access to hardware accelerated surfaces which
+// can be used in association with EGL to provide accelerated drawing.
+class GbmSurface : public ScanoutSurface {
+ public:
+ GbmSurface(gbm_device* device, DriWrapper* dri, const gfx::Size& size);
+ virtual ~GbmSurface();
+
+ // ScanoutSurface:
+ virtual bool Initialize() OVERRIDE;
+ virtual uint32_t GetFramebufferId() const OVERRIDE;
+ virtual uint32_t GetHandle() const OVERRIDE;
+ virtual gfx::Size Size() const OVERRIDE;
+ virtual void SwapBuffers() OVERRIDE;
+
+ // Before scheduling the backbuffer to be scanned out we need to "lock" it.
+ // When we lock it, GBM will give a pointer to a buffer representing the
+ // backbuffer. It will also update its information on which buffers can not be
+ // used for drawing. The buffer will be released when the page flip event
+ // occurs (see SwapBuffers). This is called from GbmSurfaceFactory before
+ // scheduling a page flip.
+ void LockCurrentDrawable();
+
+ gbm_surface* native_surface() { return native_surface_; };
+
+ private:
+ gbm_device* gbm_device_;
+
+ DriWrapper* dri_;
+
+ gfx::Size size_;
+
+ // The native GBM surface. In EGL this represents the EGLNativeWindowType.
+ gbm_surface* native_surface_;
+
+ // Backing GBM buffers. One is the current front buffer. The other is the
+ // current backbuffer that is pending scan out.
+ gbm_bo* buffers_[2];
+
+ // Index to the front buffer.
+ int front_buffer_;
+
+ // We can't lock (and get) an accelerated buffer from the GBM surface until
+ // after something draws into it. But modesetting needs to happen earlier,
+ // before an actual window is created and draws. So, we create a dumb buffer
+ // for this purpose.
+ scoped_ptr<DriBuffer> dumb_buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(GbmSurface);
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_DRI_GBM_SURFACE_H_
diff --git a/ui/ozone/platform/dri/gbm_surface_factory.cc b/ui/ozone/platform/dri/gbm_surface_factory.cc
new file mode 100644
index 0000000..0c864d3
--- /dev/null
+++ b/ui/ozone/platform/dri/gbm_surface_factory.cc
@@ -0,0 +1,153 @@
+// Copyright 2014 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 "ui/ozone/platform/dri/gbm_surface_factory.h"
+
+#include <EGL/egl.h>
+
+#include "base/files/file_path.h"
+#include "ui/gfx/ozone/surface_ozone_egl.h"
+#include "ui/ozone/platform/dri/dri_vsync_provider.h"
+#include "ui/ozone/platform/dri/gbm_surface.h"
+#include "ui/ozone/platform/dri/hardware_display_controller.h"
+#include "ui/ozone/platform/dri/scanout_surface.h"
+#include "ui/ozone/platform/dri/screen_manager.h"
+
+namespace ui {
+
+namespace {
+
+class GbmSurfaceAdapter : public gfx::SurfaceOzoneEGL {
+ public:
+ GbmSurfaceAdapter(const base::WeakPtr<HardwareDisplayController>& controller);
+ virtual ~GbmSurfaceAdapter();
+
+ // SurfaceOzoneEGL:
+ virtual intptr_t GetNativeWindow() OVERRIDE;
+ virtual bool ResizeNativeWindow(const gfx::Size& viewport_size) OVERRIDE;
+ virtual bool OnSwapBuffers() OVERRIDE;
+ virtual scoped_ptr<gfx::VSyncProvider> CreateVSyncProvider() OVERRIDE;
+
+ private:
+ base::WeakPtr<HardwareDisplayController> controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(GbmSurfaceAdapter);
+};
+
+GbmSurfaceAdapter::GbmSurfaceAdapter(
+ const base::WeakPtr<HardwareDisplayController>& controller)
+ : controller_(controller) {}
+
+GbmSurfaceAdapter::~GbmSurfaceAdapter() {}
+
+intptr_t GbmSurfaceAdapter::GetNativeWindow() {
+ if (!controller_)
+ return 0;
+
+ return reinterpret_cast<intptr_t>(
+ static_cast<GbmSurface*>(controller_->surface())->native_surface());
+}
+
+bool GbmSurfaceAdapter::ResizeNativeWindow(const gfx::Size& viewport_size) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+bool GbmSurfaceAdapter::OnSwapBuffers() {
+ if (!controller_)
+ return false;
+
+ static_cast<GbmSurface*>(controller_->surface())->LockCurrentDrawable();
+ if (controller_->SchedulePageFlip()) {
+ controller_->WaitForPageFlipEvent();
+ return true;
+ }
+
+ return false;
+}
+
+scoped_ptr<gfx::VSyncProvider> GbmSurfaceAdapter::CreateVSyncProvider() {
+ return scoped_ptr<gfx::VSyncProvider>(new DriVSyncProvider(controller_));
+}
+
+} // namespace
+
+GbmSurfaceFactory::GbmSurfaceFactory(DriWrapper* dri,
+ gbm_device* device,
+ ScreenManager* screen_manager)
+ : DriSurfaceFactory(dri, screen_manager),
+ device_(device) {}
+
+GbmSurfaceFactory::~GbmSurfaceFactory() {}
+
+intptr_t GbmSurfaceFactory::GetNativeDisplay() {
+ CHECK(state_ == INITIALIZED);
+ return reinterpret_cast<intptr_t>(device_);
+}
+
+const int32* GbmSurfaceFactory::GetEGLSurfaceProperties(
+ const int32* desired_list) {
+ static const int32 kConfigAttribs[] = {
+ EGL_BUFFER_SIZE, 32,
+ EGL_ALPHA_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_RED_SIZE, 8,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_NONE
+ };
+
+ return kConfigAttribs;
+}
+
+bool GbmSurfaceFactory::LoadEGLGLES2Bindings(
+ AddGLLibraryCallback add_gl_library,
+ SetGLGetProcAddressProcCallback set_gl_get_proc_address) {
+ base::NativeLibraryLoadError error;
+ base::NativeLibrary gles_library = base::LoadNativeLibrary(
+ base::FilePath("libGLESv2.so.2"),
+ &error);
+ if (!gles_library) {
+ LOG(WARNING) << "Failed to load GLES library: " << error.ToString();
+ return false;
+ }
+
+ base::NativeLibrary egl_library = base::LoadNativeLibrary(
+ base::FilePath("libEGL.so.1"),
+ &error);
+ if (!egl_library) {
+ LOG(WARNING) << "Failed to load EGL library: " << error.ToString();
+ base::UnloadNativeLibrary(gles_library);
+ return false;
+ }
+
+ GLGetProcAddressProc get_proc_address =
+ reinterpret_cast<GLGetProcAddressProc>(
+ base::GetFunctionPointerFromNativeLibrary(
+ egl_library, "eglGetProcAddress"));
+ if (!get_proc_address) {
+ LOG(ERROR) << "eglGetProcAddress not found.";
+ base::UnloadNativeLibrary(egl_library);
+ base::UnloadNativeLibrary(gles_library);
+ return false;
+ }
+
+ set_gl_get_proc_address.Run(get_proc_address);
+ add_gl_library.Run(egl_library);
+ add_gl_library.Run(gles_library);
+
+ return true;
+}
+
+scoped_ptr<gfx::SurfaceOzoneEGL> GbmSurfaceFactory::CreateEGLSurfaceForWidget(
+ gfx::AcceleratedWidget w) {
+ CHECK(state_ == INITIALIZED);
+ ResetCursor(w);
+
+ return scoped_ptr<gfx::SurfaceOzoneEGL>(
+ new GbmSurfaceAdapter(screen_manager_->GetDisplayController(w)));
+}
+
+} // namespace ui
diff --git a/ui/ozone/platform/dri/gbm_surface_factory.h b/ui/ozone/platform/dri/gbm_surface_factory.h
new file mode 100644
index 0000000..2fe0199
--- /dev/null
+++ b/ui/ozone/platform/dri/gbm_surface_factory.h
@@ -0,0 +1,39 @@
+// Copyright 2014 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 UI_OZONE_PLATFORM_DRI_GBM_SURFACE_FACTORY_H_
+#define UI_OZONE_PLATFORM_DRI_GBM_SURFACE_FACTORY_H_
+
+#include "ui/ozone/platform/dri/dri_surface_factory.h"
+
+struct gbm_device;
+
+namespace ui {
+
+class GbmSurfaceFactory : public DriSurfaceFactory {
+ public:
+ GbmSurfaceFactory(DriWrapper* dri,
+ gbm_device* device,
+ ScreenManager* screen_manager);
+ virtual ~GbmSurfaceFactory();
+
+ // DriSurfaceFactory:
+ virtual intptr_t GetNativeDisplay() OVERRIDE;
+ virtual const int32_t* GetEGLSurfaceProperties(
+ const int32_t* desired_list) OVERRIDE;
+ virtual bool LoadEGLGLES2Bindings(
+ AddGLLibraryCallback add_gl_library,
+ SetGLGetProcAddressProcCallback set_gl_get_proc_address) OVERRIDE;
+ virtual scoped_ptr<gfx::SurfaceOzoneEGL> CreateEGLSurfaceForWidget(
+ gfx::AcceleratedWidget w) OVERRIDE;
+
+ private:
+ gbm_device* device_; // Not owned.
+
+ DISALLOW_COPY_AND_ASSIGN(GbmSurfaceFactory);
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_DRI_GBM_SURFACE_FACTORY_H_
diff --git a/ui/ozone/platform/dri/hardware_display_controller.cc b/ui/ozone/platform/dri/hardware_display_controller.cc
index 6256aee..e6ce1f5 100644
--- a/ui/ozone/platform/dri/hardware_display_controller.cc
+++ b/ui/ozone/platform/dri/hardware_display_controller.cc
@@ -15,9 +15,10 @@
#include "base/time/time.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/size.h"
#include "ui/ozone/platform/dri/dri_buffer.h"
-#include "ui/ozone/platform/dri/dri_surface.h"
#include "ui/ozone/platform/dri/dri_wrapper.h"
+#include "ui/ozone/platform/dri/scanout_surface.h"
namespace ui {
@@ -28,7 +29,7 @@ namespace {
// The old frontbuffer is no longer used by the hardware and can be used for
// future draw operations.
//
-// |device| will contain a reference to the |DriSurface| object which
+// |device| will contain a reference to the |ScanoutSurface| object which
// the event belongs to.
//
// TODO(dnicoara) When we have a FD handler for the DRM calls in the message
@@ -63,7 +64,7 @@ HardwareDisplayController::~HardwareDisplayController() {
bool
HardwareDisplayController::BindSurfaceToController(
- scoped_ptr<DriSurface> surface, drmModeModeInfo mode) {
+ scoped_ptr<ScanoutSurface> surface, drmModeModeInfo mode) {
CHECK(surface);
if (!drm_->SetCrtc(crtc_id_,
@@ -94,7 +95,6 @@ void HardwareDisplayController::Disable() {
bool HardwareDisplayController::SchedulePageFlip() {
CHECK(surface_);
-
if (!drm_->PageFlip(crtc_id_,
surface_->GetFramebufferId(),
this)) {
@@ -127,11 +127,11 @@ void HardwareDisplayController::OnPageFlipEvent(unsigned int frame,
surface_->SwapBuffers();
}
-bool HardwareDisplayController::SetCursor(DriSurface* surface) {
+bool HardwareDisplayController::SetCursor(ScanoutSurface* surface) {
bool ret = drm_->SetCursor(crtc_id_,
surface->GetHandle(),
- surface->size().width(),
- surface->size().height());
+ surface->Size().width(),
+ surface->Size().height());
surface->SwapBuffers();
return ret;
}
diff --git a/ui/ozone/platform/dri/hardware_display_controller.h b/ui/ozone/platform/dri/hardware_display_controller.h
index 11320b3..812f084 100644
--- a/ui/ozone/platform/dri/hardware_display_controller.h
+++ b/ui/ozone/platform/dri/hardware_display_controller.h
@@ -22,7 +22,7 @@ class Point;
namespace ui {
-class DriSurface;
+class ScanoutSurface;
// The HDCOz will handle modesettings and scannout operations for hardware
// devices.
@@ -91,7 +91,7 @@ class OZONE_EXPORT HardwareDisplayController
~HardwareDisplayController();
// Associate the HDCO with a surface implementation and initialize it.
- bool BindSurfaceToController(scoped_ptr<DriSurface> surface,
+ bool BindSurfaceToController(scoped_ptr<ScanoutSurface> surface,
drmModeModeInfo mode);
void UnbindSurfaceFromController();
@@ -132,7 +132,7 @@ class OZONE_EXPORT HardwareDisplayController
unsigned int useconds);
// Set the hardware cursor to show the contents of |surface|.
- bool SetCursor(DriSurface* surface);
+ bool SetCursor(ScanoutSurface* surface);
bool UnsetCursor();
@@ -142,7 +142,7 @@ class OZONE_EXPORT HardwareDisplayController
const drmModeModeInfo& get_mode() const { return mode_; };
uint32_t connector_id() const { return connector_id_; }
uint32_t crtc_id() const { return crtc_id_; }
- DriSurface* surface() const {
+ ScanoutSurface* surface() const {
return surface_.get();
};
@@ -163,7 +163,7 @@ class OZONE_EXPORT HardwareDisplayController
// TODO(dnicoara) Need to store all the modes.
drmModeModeInfo mode_;
- scoped_ptr<DriSurface> surface_;
+ scoped_ptr<ScanoutSurface> surface_;
uint64_t time_of_last_flip_;
diff --git a/ui/ozone/platform/dri/hardware_display_controller_unittest.cc b/ui/ozone/platform/dri/hardware_display_controller_unittest.cc
index 9a3e5dc..37ea856 100644
--- a/ui/ozone/platform/dri/hardware_display_controller_unittest.cc
+++ b/ui/ozone/platform/dri/hardware_display_controller_unittest.cc
@@ -47,7 +47,7 @@ void HardwareDisplayControllerTest::TearDown() {
}
TEST_F(HardwareDisplayControllerTest, CheckStateAfterSurfaceIsBound) {
- scoped_ptr<ui::DriSurface> surface(
+ scoped_ptr<ui::ScanoutSurface> surface(
new ui::MockDriSurface(drm_.get(), kDefaultModeSize));
EXPECT_TRUE(surface->Initialize());
@@ -57,7 +57,7 @@ TEST_F(HardwareDisplayControllerTest, CheckStateAfterSurfaceIsBound) {
}
TEST_F(HardwareDisplayControllerTest, CheckStateAfterPageFlip) {
- scoped_ptr<ui::DriSurface> surface(
+ scoped_ptr<ui::ScanoutSurface> surface(
new ui::MockDriSurface(drm_.get(), kDefaultModeSize));
EXPECT_TRUE(surface->Initialize());
@@ -70,7 +70,7 @@ TEST_F(HardwareDisplayControllerTest, CheckStateAfterPageFlip) {
TEST_F(HardwareDisplayControllerTest, CheckStateIfModesetFails) {
drm_->set_set_crtc_expectation(false);
- scoped_ptr<ui::DriSurface> surface(
+ scoped_ptr<ui::ScanoutSurface> surface(
new ui::MockDriSurface(drm_.get(), kDefaultModeSize));
EXPECT_TRUE(surface->Initialize());
@@ -82,7 +82,7 @@ TEST_F(HardwareDisplayControllerTest, CheckStateIfModesetFails) {
TEST_F(HardwareDisplayControllerTest, CheckStateIfPageFlipFails) {
drm_->set_page_flip_expectation(false);
- scoped_ptr<ui::DriSurface> surface(
+ scoped_ptr<ui::ScanoutSurface> surface(
new ui::MockDriSurface(drm_.get(), kDefaultModeSize));
EXPECT_TRUE(surface->Initialize());
diff --git a/ui/ozone/platform/dri/ozone_platform_dri.cc b/ui/ozone/platform/dri/ozone_platform_dri.cc
index d701bee..442b485 100644
--- a/ui/ozone/platform/dri/ozone_platform_dri.cc
+++ b/ui/ozone/platform/dri/ozone_platform_dri.cc
@@ -9,8 +9,10 @@
#include "ui/events/ozone/evdev/event_factory_evdev.h"
#include "ui/ozone/ozone_platform.h"
#include "ui/ozone/platform/dri/cursor_factory_evdev_dri.h"
+#include "ui/ozone/platform/dri/dri_surface.h"
#include "ui/ozone/platform/dri/dri_surface_factory.h"
#include "ui/ozone/platform/dri/dri_wrapper.h"
+#include "ui/ozone/platform/dri/scanout_surface.h"
#include "ui/ozone/platform/dri/screen_manager.h"
#if defined(OS_CHROMEOS)
@@ -24,6 +26,21 @@ namespace {
const char kDefaultGraphicsCardPath[] = "/dev/dri/card0";
+class DriSurfaceGenerator : public ScanoutSurfaceGenerator {
+ public:
+ DriSurfaceGenerator(DriWrapper* dri) : dri_(dri) {}
+ virtual ~DriSurfaceGenerator() {}
+
+ virtual ScanoutSurface* Create(const gfx::Size& size) OVERRIDE {
+ return new DriSurface(dri_, size);
+ }
+
+ private:
+ DriWrapper* dri_; // Not owned.
+
+ DISALLOW_COPY_AND_ASSIGN(DriSurfaceGenerator);
+};
+
// OzonePlatform for Linux DRI (Direct Rendering Infrastructure)
//
// This platform is Linux without any display server (no X, wayland, or
@@ -32,7 +49,9 @@ class OzonePlatformDri : public OzonePlatform {
public:
OzonePlatformDri()
: dri_(new DriWrapper(kDefaultGraphicsCardPath)),
- screen_manager_(new ScreenManager(dri_.get())),
+ surface_generator_(new DriSurfaceGenerator(dri_.get())),
+ screen_manager_(new ScreenManager(dri_.get(),
+ surface_generator_.get())),
device_manager_(CreateDeviceManager()) {}
virtual ~OzonePlatformDri() {}
@@ -71,6 +90,7 @@ class OzonePlatformDri : public OzonePlatform {
private:
scoped_ptr<DriWrapper> dri_;
+ scoped_ptr<DriSurfaceGenerator> surface_generator_;
// TODO(dnicoara) Move ownership of |screen_manager_| to NDD.
scoped_ptr<ScreenManager> screen_manager_;
scoped_ptr<DeviceManager> device_manager_;
diff --git a/ui/ozone/platform/dri/ozone_platform_gbm.cc b/ui/ozone/platform/dri/ozone_platform_gbm.cc
new file mode 100644
index 0000000..46e3bac
--- /dev/null
+++ b/ui/ozone/platform/dri/ozone_platform_gbm.cc
@@ -0,0 +1,114 @@
+// Copyright 2014 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 "ui/ozone/platform/dri/ozone_platform_gbm.h"
+
+#include <stdlib.h>
+#include <gbm.h>
+
+#include "ui/base/cursor/ozone/cursor_factory_ozone.h"
+#include "ui/events/ozone/device/device_manager.h"
+#include "ui/events/ozone/evdev/event_factory_evdev.h"
+#include "ui/ozone/ozone_platform.h"
+#include "ui/ozone/platform/dri/dri_wrapper.h"
+#include "ui/ozone/platform/dri/gbm_surface.h"
+#include "ui/ozone/platform/dri/gbm_surface_factory.h"
+#include "ui/ozone/platform/dri/scanout_surface.h"
+#include "ui/ozone/platform/dri/screen_manager.h"
+
+#if defined(OS_CHROMEOS)
+#include "ui/ozone/common/chromeos/native_display_delegate_ozone.h"
+#endif
+
+namespace ui {
+
+namespace {
+
+const char kDefaultGraphicsCardPath[] = "/dev/dri/card0";
+
+class GbmSurfaceGenerator : public ScanoutSurfaceGenerator {
+ public:
+ GbmSurfaceGenerator(DriWrapper* dri)
+ : dri_(dri),
+ device_(gbm_create_device(dri_->get_fd())) {}
+ virtual ~GbmSurfaceGenerator() {
+ gbm_device_destroy(device_);
+ }
+
+ gbm_device* device() const { return device_; }
+
+ virtual ScanoutSurface* Create(const gfx::Size& size) OVERRIDE {
+ return new GbmSurface(device_, dri_, size);
+ }
+
+ private:
+ DriWrapper* dri_; // Not owned.
+
+ gbm_device* device_;
+
+ DISALLOW_COPY_AND_ASSIGN(GbmSurfaceGenerator);
+};
+
+class OzonePlatformGbm : public OzonePlatform {
+ public:
+ OzonePlatformGbm() {}
+ virtual ~OzonePlatformGbm() {}
+
+ // OzonePlatform:
+ virtual gfx::SurfaceFactoryOzone* GetSurfaceFactoryOzone() OVERRIDE {
+ return surface_factory_ozone_.get();
+ }
+ virtual EventFactoryOzone* GetEventFactoryOzone() OVERRIDE {
+ return event_factory_ozone_.get();
+ }
+ virtual CursorFactoryOzone* GetCursorFactoryOzone() OVERRIDE {
+ return cursor_factory_ozone_.get();
+ }
+#if defined(OS_CHROMEOS)
+ virtual scoped_ptr<NativeDisplayDelegate> CreateNativeDisplayDelegate()
+ OVERRIDE {
+ return scoped_ptr<NativeDisplayDelegate>(new NativeDisplayDelegateOzone());
+ }
+#endif
+ virtual void InitializeUI() OVERRIDE {
+ // Needed since the browser process creates the accelerated widgets and that
+ // happens through SFO.
+ surface_factory_ozone_.reset(new GbmSurfaceFactory(NULL, NULL, NULL));
+
+ device_manager_ = CreateDeviceManager();
+ cursor_factory_ozone_.reset(new CursorFactoryOzone());
+ event_factory_ozone_.reset(new EventFactoryEvdev(
+ NULL, device_manager_.get()));
+ }
+
+ virtual void InitializeGPU() OVERRIDE {
+ dri_.reset(new DriWrapper(kDefaultGraphicsCardPath));
+ surface_generator_.reset(new GbmSurfaceGenerator(dri_.get()));
+ screen_manager_.reset(new ScreenManager(dri_.get(),
+ surface_generator_.get()));
+ surface_factory_ozone_.reset(
+ new GbmSurfaceFactory(dri_.get(),
+ surface_generator_->device(),
+ screen_manager_.get()));
+ }
+
+ private:
+ scoped_ptr<DriWrapper> dri_;
+ scoped_ptr<GbmSurfaceGenerator> surface_generator_;
+ // TODO(dnicoara) Move ownership of |screen_manager_| to NDD.
+ scoped_ptr<ScreenManager> screen_manager_;
+ scoped_ptr<DeviceManager> device_manager_;
+
+ scoped_ptr<GbmSurfaceFactory> surface_factory_ozone_;
+ scoped_ptr<CursorFactoryOzone> cursor_factory_ozone_;
+ scoped_ptr<EventFactoryEvdev> event_factory_ozone_;
+
+ DISALLOW_COPY_AND_ASSIGN(OzonePlatformGbm);
+};
+
+} // namespace
+
+OzonePlatform* CreateOzonePlatformGbm() { return new OzonePlatformGbm; }
+
+} // namespace ui
diff --git a/ui/ozone/platform/dri/ozone_platform_gbm.h b/ui/ozone/platform/dri/ozone_platform_gbm.h
new file mode 100644
index 0000000..47f5ca7
--- /dev/null
+++ b/ui/ozone/platform/dri/ozone_platform_gbm.h
@@ -0,0 +1,17 @@
+// Copyright 2014 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 UI_OZONE_PLATFORM_DRI_OZONE_PLATFORM_GBM_H_
+#define UI_OZONE_PLATFORM_DRI_OZONE_PLATFORM_GBM_H_
+
+namespace ui {
+
+class OzonePlatform;
+
+// Constructor hook for use in ozone_platform_list.cc
+OzonePlatform* CreateOzonePlatformGbm();
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_DRI_OZONE_PLATFORM_GBM_H_
diff --git a/ui/ozone/platform/dri/scanout_surface.h b/ui/ozone/platform/dri/scanout_surface.h
new file mode 100644
index 0000000..d362ae1
--- /dev/null
+++ b/ui/ozone/platform/dri/scanout_surface.h
@@ -0,0 +1,84 @@
+// Copyright 2014 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 UI_OZONE_PLATFORM_DRI_SCANOUT_SURFACE_H_
+#define UI_OZONE_PLATFORM_DRI_SCANOUT_SURFACE_H_
+
+#include <stdint.h>
+
+namespace gfx {
+class Size;
+}
+
+namespace ui {
+
+// ScanoutSurface is an interface for a surface that can be scanned out to a
+// monitor using the DRM/KMS API. Implementations will store the internal state
+// associated with the drawing surface. Implementations are also required to
+// performs all the needed operations to initialize and update the drawing
+// surface.
+//
+// The typical usage pattern is:
+// -----------------------------------------------------------------------------
+// HardwareDisplayController controller;
+// // Initialize controller
+//
+// ScanoutSurface* surface = new ScanoutSurfaceImpl(size);
+// surface.Initialize();
+// controller.BindSurfaceToController(surface);
+//
+// while (true) {
+// DrawIntoSurface(surface);
+// controller.SchedulePageFlip();
+//
+// Wait for page flip event. The DRM page flip handler will call
+// surface.SwapBuffers();
+// }
+//
+// delete surface;
+// -----------------------------------------------------------------------------
+// In the above example the wait consists of reading a DRM pageflip event from
+// the graphics card file descriptor. This is done by calling |drmHandleEvent|,
+// which will read and process the event. |drmHandleEvent| will call a callback
+// registered by |SchedulePageFlip| which will update the internal state.
+//
+// |SchedulePageFlip| can also be used to limit drawing to the screen's vsync
+// since page flips only happen on vsync. In a threaded environment a message
+// loop would listen on the graphics card file descriptor for an event and
+// |drmHandleEvent| would be called from the message loop. The event handler
+// would also be responsible for updating the renderer's state and signal that
+// it is OK to start drawing the next frame.
+class ScanoutSurface {
+ public:
+ virtual ~ScanoutSurface() {}
+
+ // Used to allocate all necessary buffers for this surface. If the
+ // initialization succeeds, the device is ready to be used for drawing
+ // operations.
+ // Returns true if the initialization is successful, false otherwise.
+ virtual bool Initialize() = 0;
+
+ // Swaps the back buffer with the front buffer.
+ virtual void SwapBuffers() = 0;
+
+ // Returns the ID of the current backbuffer.
+ virtual uint32_t GetFramebufferId() const = 0;
+
+ // Returns the handle of the current backbuffer.
+ virtual uint32_t GetHandle() const = 0;
+
+ // Returns the surface size.
+ virtual gfx::Size Size() const = 0;
+};
+
+class ScanoutSurfaceGenerator {
+ public:
+ virtual ~ScanoutSurfaceGenerator() {}
+
+ virtual ScanoutSurface* Create(const gfx::Size& size) = 0;
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_DRI_SCANOUT_SURFACE_H_
diff --git a/ui/ozone/platform/dri/screen_manager.cc b/ui/ozone/platform/dri/screen_manager.cc
index bf01636..23a43f9 100644
--- a/ui/ozone/platform/dri/screen_manager.cc
+++ b/ui/ozone/platform/dri/screen_manager.cc
@@ -9,14 +9,15 @@
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
-#include "ui/ozone/platform/dri/dri_surface.h"
#include "ui/ozone/platform/dri/dri_util.h"
#include "ui/ozone/platform/dri/hardware_display_controller.h"
+#include "ui/ozone/platform/dri/scanout_surface.h"
namespace ui {
-ScreenManager::ScreenManager(DriWrapper* dri)
- : dri_(dri), last_added_widget_(0) {
+ScreenManager::ScreenManager(
+ DriWrapper* dri, ScanoutSurfaceGenerator* surface_generator)
+ : dri_(dri), surface_generator_(surface_generator), last_added_widget_(0) {
}
ScreenManager::~ScreenManager() {
@@ -51,8 +52,8 @@ bool ScreenManager::ConfigureDisplayController(uint32_t crtc,
}
// Create a surface suitable for the current controller.
- scoped_ptr<DriSurface> surface(
- CreateSurface(gfx::Size(mode.hdisplay, mode.vdisplay)));
+ scoped_ptr<ScanoutSurface> surface(
+ surface_generator_->Create(gfx::Size(mode.hdisplay, mode.vdisplay)));
if (!surface->Initialize()) {
LOG(ERROR) << "Failed to initialize surface";
@@ -131,8 +132,4 @@ void ScreenManager::ForceInitializationOfPrimaryDisplay() {
displays[0]->connector()->modes[0]);
}
-DriSurface* ScreenManager::CreateSurface(const gfx::Size& size) {
- return new DriSurface(dri_, size);
-}
-
} // namespace ui
diff --git a/ui/ozone/platform/dri/screen_manager.h b/ui/ozone/platform/dri/screen_manager.h
index 252f706..fbe7bbb 100644
--- a/ui/ozone/platform/dri/screen_manager.h
+++ b/ui/ozone/platform/dri/screen_manager.h
@@ -23,11 +23,12 @@ class Size;
namespace ui {
class DriWrapper;
+class ScanoutSurfaceGenerator;
// Responsible for keeping track of active displays and configuring them.
class OZONE_EXPORT ScreenManager {
public:
- ScreenManager(DriWrapper* dri);
+ ScreenManager(DriWrapper* dri, ScanoutSurfaceGenerator* surface_generator);
virtual ~ScreenManager();
// Remove a display controller from the list of active controllers. The
@@ -68,9 +69,8 @@ class OZONE_EXPORT ScreenManager {
// to initialize a display.
virtual void ForceInitializationOfPrimaryDisplay();
- virtual DriSurface* CreateSurface(const gfx::Size& size);
-
DriWrapper* dri_; // Not owned.
+ ScanoutSurfaceGenerator* surface_generator_; // Not owned.
// Mapping between an accelerated widget and an active display.
HardwareDisplayControllerMap controllers_;
gfx::AcceleratedWidget last_added_widget_;
diff --git a/ui/ozone/platform/dri/screen_manager_unittest.cc b/ui/ozone/platform/dri/screen_manager_unittest.cc
index 457bef7..ce50f4b 100644
--- a/ui/ozone/platform/dri/screen_manager_unittest.cc
+++ b/ui/ozone/platform/dri/screen_manager_unittest.cc
@@ -5,8 +5,8 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/ozone/platform/dri/hardware_display_controller.h"
#include "ui/ozone/platform/dri/screen_manager.h"
-#include "ui/ozone/platform/dri/test/mock_dri_surface.h"
#include "ui/ozone/platform/dri/test/mock_dri_wrapper.h"
+#include "ui/ozone/platform/dri/test/mock_surface_generator.h"
namespace {
@@ -16,12 +16,11 @@ const drmModeModeInfo kDefaultMode =
class MockScreenManager : public ui::ScreenManager {
public:
- MockScreenManager(ui::DriWrapper* dri) : ScreenManager(dri), dri_(dri) {}
+ MockScreenManager(ui::DriWrapper* dri,
+ ui::ScanoutSurfaceGenerator* surface_generator)
+ : ScreenManager(dri, surface_generator), dri_(dri) {}
virtual void ForceInitializationOfPrimaryDisplay() OVERRIDE {}
- virtual ui::DriSurface* CreateSurface(const gfx::Size& size) OVERRIDE {
- return new ui::MockDriSurface(dri_, size);
- }
private:
ui::DriWrapper* dri_;
@@ -38,7 +37,9 @@ class ScreenManagerTest : public testing::Test {
virtual void SetUp() OVERRIDE {
dri_.reset(new ui::MockDriWrapper(3));
- screen_manager_.reset(new MockScreenManager(dri_.get()));
+ surface_generator_.reset(new ui::MockSurfaceGenerator(dri_.get()));
+ screen_manager_.reset(new MockScreenManager(
+ dri_.get(), surface_generator_.get()));
}
virtual void TearDown() OVERRIDE {
screen_manager_.reset();
@@ -47,6 +48,7 @@ class ScreenManagerTest : public testing::Test {
protected:
scoped_ptr<ui::MockDriWrapper> dri_;
+ scoped_ptr<ui::MockSurfaceGenerator> surface_generator_;
scoped_ptr<MockScreenManager> screen_manager_;
private:
diff --git a/ui/ozone/platform/dri/test/mock_surface_generator.cc b/ui/ozone/platform/dri/test/mock_surface_generator.cc
new file mode 100644
index 0000000..97df5bd
--- /dev/null
+++ b/ui/ozone/platform/dri/test/mock_surface_generator.cc
@@ -0,0 +1,18 @@
+// Copyright 2014 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 "ui/ozone/platform/dri/test/mock_surface_generator.h"
+
+namespace ui {
+
+MockSurfaceGenerator::MockSurfaceGenerator(DriWrapper* dri) : dri_(dri) {}
+
+MockSurfaceGenerator::~MockSurfaceGenerator() {}
+
+ScanoutSurface* MockSurfaceGenerator::Create(const gfx::Size& size) {
+ surfaces_.push_back(new MockDriSurface(dri_, size));
+ return surfaces_.back();
+}
+
+} // namespace ui
diff --git a/ui/ozone/platform/dri/test/mock_surface_generator.h b/ui/ozone/platform/dri/test/mock_surface_generator.h
new file mode 100644
index 0000000..d9b77f8
--- /dev/null
+++ b/ui/ozone/platform/dri/test/mock_surface_generator.h
@@ -0,0 +1,40 @@
+// Copyright 2014 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 UI_OZONE_PLATFORM_DRI_TEST_MOCK_SURFACE_GENERATOR_H_
+#define UI_OZONE_PLATFORM_DRI_TEST_MOCK_SURFACE_GENERATOR_H_
+
+#include <vector>
+
+#include "ui/ozone/platform/dri/test/mock_dri_surface.h"
+
+namespace gfx {
+class Size;
+}
+
+namespace ui {
+
+class DriWrapper;
+
+class MockSurfaceGenerator : public ScanoutSurfaceGenerator {
+ public:
+ MockSurfaceGenerator(DriWrapper* dri);
+ virtual ~MockSurfaceGenerator();
+
+ std::vector<MockDriSurface*> surfaces() const { return surfaces_; }
+
+ // ScanoutSurfaceGenerator:
+ virtual ScanoutSurface* Create(const gfx::Size& size) OVERRIDE;
+
+ private:
+ DriWrapper* dri_; // Not owned.
+
+ std::vector<MockDriSurface*> surfaces_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockSurfaceGenerator);
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_DRI_TEST_MOCK_SURFACE_GENERATOR_H_