Commit 7cc1c39b authored by dnicoara@chromium.org's avatar dnicoara@chromium.org

[Ozone-DRI] Remove unneeded wrappers

 * Merging DriSurfaceAdaptor into DriSurface
 * Merging GbmSurfaceAdaptor into GbmSurface
 * Extracting GbmSurfaceless implementation into separate class & having
GbmSurface extend it
 * Remove ScanoutSurface

Depends on https://codereview.chromium.org/393233005

BUG=none
NOTRY=true

Review URL: https://codereview.chromium.org/403043004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@284710 0039d316-1c4b-4281-b951-d872f2087c98
parent 54692fcd
...@@ -66,7 +66,6 @@ ...@@ -66,7 +66,6 @@
'screen_manager.cc', 'screen_manager.cc',
'screen_manager.h', 'screen_manager.h',
'scanout_buffer.h', 'scanout_buffer.h',
'scanout_surface.h',
'virtual_terminal_manager.cc', 'virtual_terminal_manager.cc',
'virtual_terminal_manager.h', 'virtual_terminal_manager.h',
], ],
...@@ -74,7 +73,7 @@ ...@@ -74,7 +73,7 @@
['use_drm_atomic_flip==1', { ['use_drm_atomic_flip==1', {
'sources': [ 'sources': [
'hardware_display_plane.cc', 'hardware_display_plane.cc',
'hardware_display_plane.h', 'hardware_display_plane.h',
], ],
}], }],
], ],
......
...@@ -4,75 +4,98 @@ ...@@ -4,75 +4,98 @@
#include "ui/ozone/platform/dri/dri_surface.h" #include "ui/ozone/platform/dri/dri_surface.h"
#include <errno.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <xf86drm.h>
#include "base/logging.h" #include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
#include "ui/gfx/skia_util.h" #include "ui/gfx/skia_util.h"
#include "ui/ozone/platform/dri/dri_buffer.h" #include "ui/ozone/platform/dri/dri_buffer.h"
#include "ui/ozone/platform/dri/dri_vsync_provider.h"
#include "ui/ozone/platform/dri/dri_wrapper.h" #include "ui/ozone/platform/dri/dri_wrapper.h"
#include "ui/ozone/platform/dri/hardware_display_controller.h"
namespace ui { namespace ui {
namespace {
scoped_refptr<DriBuffer> AllocateBuffer(DriWrapper* dri,
const gfx::Size& size) {
scoped_refptr<DriBuffer> buffer(new DriBuffer(dri));
SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height());
CHECK(buffer->Initialize(info)) << "Failed to create drm buffer.";
return buffer;
}
} // namespace
DriSurface::DriSurface( DriSurface::DriSurface(
DriWrapper* dri, const gfx::Size& size) DriWrapper* dri,
const base::WeakPtr<HardwareDisplayController>& controller)
: dri_(dri), : dri_(dri),
bitmaps_(), buffers_(),
front_buffer_(0), front_buffer_(0),
size_(size) { controller_(controller) {
} }
DriSurface::~DriSurface() { DriSurface::~DriSurface() {
} }
bool DriSurface::Initialize() { skia::RefPtr<SkCanvas> DriSurface::GetCanvas() {
for (size_t i = 0; i < arraysize(bitmaps_); ++i) { return skia::SharePtr(surface_->getCanvas());
bitmaps_[i] = new DriBuffer(dri_);
// TODO(dnicoara) Should select the configuration based on what the
// underlying system supports.
SkImageInfo info = SkImageInfo::MakeN32Premul(size_.width(),
size_.height());
if (!bitmaps_[i]->Initialize(info)) {
return false;
}
}
return true;
} }
uint32_t DriSurface::GetFramebufferId() const { void DriSurface::ResizeCanvas(const gfx::Size& viewport_size) {
CHECK(backbuffer()); SkImageInfo info = SkImageInfo::MakeN32(
return backbuffer()->GetFramebufferId(); viewport_size.width(), viewport_size.height(), kOpaque_SkAlphaType);
} surface_ = skia::AdoptRef(SkSurface::NewRaster(info));
uint32_t DriSurface::GetHandle() const { if (!controller_)
CHECK(backbuffer()); return;
return backbuffer()->GetHandle();
}
void DriSurface::PreSwapBuffers() { // For the display buffers use the mode size since a |viewport_size| smaller
// than the display size will not scanout.
gfx::Size mode_size(controller_->get_mode().hdisplay,
controller_->get_mode().vdisplay);
for (size_t i = 0; i < arraysize(buffers_); ++i)
buffers_[i] = AllocateBuffer(dri_, mode_size);
} }
// This call is made after the hardware just started displaying our back buffer. void DriSurface::PresentCanvas(const gfx::Rect& damage) {
// We need to update our pointer reference and synchronize the two buffers. CHECK(base::MessageLoopForUI::IsCurrent());
void DriSurface::SwapBuffers() { CHECK(buffers_[front_buffer_ ^ 1]);
CHECK(backbuffer());
if (!controller_)
return;
std::vector<OverlayPlane> planes(
1, OverlayPlane(buffers_[front_buffer_ ^ 1]));
UpdateNativeSurface(damage);
if (controller_->SchedulePageFlip(planes))
controller_->WaitForPageFlipEvent();
// Update our front buffer pointer. // Update our front buffer pointer.
front_buffer_ ^= 1; front_buffer_ ^= 1;
} }
gfx::Size DriSurface::Size() const { scoped_ptr<gfx::VSyncProvider> DriSurface::CreateVSyncProvider() {
return size_; return scoped_ptr<gfx::VSyncProvider>(new DriVSyncProvider(controller_));
} }
SkCanvas* DriSurface::GetDrawableForWidget() { void DriSurface::UpdateNativeSurface(const gfx::Rect& damage) {
CHECK(backbuffer()); SkCanvas* canvas = buffers_[front_buffer_ ^ 1]->GetCanvas();
return backbuffer()->GetCanvas();
// The DriSurface is double buffered, so the current back buffer is
// missing the previous update. Expand damage region.
SkRect real_damage = RectToSkRect(UnionRects(damage, last_damage_));
// Copy damage region.
skia::RefPtr<SkImage> image = skia::AdoptRef(surface_->newImageSnapshot());
image->draw(canvas, &real_damage, real_damage, NULL);
last_damage_ = damage;
} }
} // namespace ui } // namespace ui
...@@ -5,53 +5,50 @@ ...@@ -5,53 +5,50 @@
#ifndef UI_OZONE_PLATFORM_DRI_DRI_SURFACE_H_ #ifndef UI_OZONE_PLATFORM_DRI_DRI_SURFACE_H_
#define UI_OZONE_PLATFORM_DRI_DRI_SURFACE_H_ #define UI_OZONE_PLATFORM_DRI_DRI_SURFACE_H_
#include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h"
#include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
#include "ui/gfx/skia_util.h" #include "ui/gfx/skia_util.h"
#include "ui/ozone/platform/dri/scanout_surface.h" #include "ui/ozone/public/surface_ozone_canvas.h"
class SkCanvas; class SkCanvas;
class SkSurface;
namespace ui { namespace ui {
class DriBuffer; class DriBuffer;
class DriWrapper; class DriWrapper;
class HardwareDisplayController;
// An implementation of ScanoutSurface which uses dumb buffers (used for class DriSurface : public SurfaceOzoneCanvas {
// software rendering).
class DriSurface : public ScanoutSurface {
public: public:
DriSurface(DriWrapper* dri, const gfx::Size& size); DriSurface(DriWrapper* dri,
const base::WeakPtr<HardwareDisplayController>& controller);
virtual ~DriSurface(); virtual ~DriSurface();
// Get a Skia canvas for a backbuffer. // SurfaceOzoneCanvas:
SkCanvas* GetDrawableForWidget(); virtual skia::RefPtr<SkCanvas> GetCanvas() OVERRIDE;
scoped_refptr<DriBuffer> backbuffer() const { virtual void ResizeCanvas(const gfx::Size& viewport_size) OVERRIDE;
return bitmaps_[front_buffer_ ^ 1]; virtual void PresentCanvas(const gfx::Rect& damage) OVERRIDE;
} virtual scoped_ptr<gfx::VSyncProvider> CreateVSyncProvider() OVERRIDE;
// ScanoutSurface:
virtual bool Initialize() OVERRIDE;
virtual uint32_t GetFramebufferId() const OVERRIDE;
virtual uint32_t GetHandle() const OVERRIDE;
virtual void PreSwapBuffers() OVERRIDE;
virtual void SwapBuffers() OVERRIDE;
virtual gfx::Size Size() const OVERRIDE;
private: private:
void UpdateNativeSurface(const gfx::Rect& damage);
// Stores the connection to the graphics card. Pointer not owned by this // Stores the connection to the graphics card. Pointer not owned by this
// class. // class.
DriWrapper* dri_; DriWrapper* dri_;
// The actual buffers used for painting. // The actual buffers used for painting.
scoped_refptr<DriBuffer> bitmaps_[2]; scoped_refptr<DriBuffer> buffers_[2];
// Keeps track of which bitmap is |buffers_| is the frontbuffer. // Keeps track of which bitmap is |buffers_| is the frontbuffer.
int front_buffer_; int front_buffer_;
// Surface size. skia::RefPtr<SkSurface> surface_;
gfx::Size size_; gfx::Rect last_damage_;
base::WeakPtr<HardwareDisplayController> controller_;
DISALLOW_COPY_AND_ASSIGN(DriSurface); DISALLOW_COPY_AND_ASSIGN(DriSurface);
}; };
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include <errno.h> #include <errno.h>
#include "base/debug/trace_event.h" #include "base/debug/trace_event.h"
#include "base/message_loop/message_loop.h"
#include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkDevice.h" #include "third_party/skia/include/core/SkDevice.h"
#include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/core/SkSurface.h"
...@@ -15,7 +14,6 @@ ...@@ -15,7 +14,6 @@
#include "ui/ozone/platform/dri/dri_buffer.h" #include "ui/ozone/platform/dri/dri_buffer.h"
#include "ui/ozone/platform/dri/dri_surface.h" #include "ui/ozone/platform/dri/dri_surface.h"
#include "ui/ozone/platform/dri/dri_util.h" #include "ui/ozone/platform/dri/dri_util.h"
#include "ui/ozone/platform/dri/dri_vsync_provider.h"
#include "ui/ozone/platform/dri/dri_wrapper.h" #include "ui/ozone/platform/dri/dri_wrapper.h"
#include "ui/ozone/platform/dri/hardware_display_controller.h" #include "ui/ozone/platform/dri/hardware_display_controller.h"
#include "ui/ozone/platform/dri/screen_manager.h" #include "ui/ozone/platform/dri/screen_manager.h"
...@@ -43,96 +41,14 @@ void UpdateCursorImage(DriBuffer* cursor, const SkBitmap& image) { ...@@ -43,96 +41,14 @@ void UpdateCursorImage(DriBuffer* cursor, const SkBitmap& image) {
canvas->drawBitmapRectToRect(image, &damage, damage); canvas->drawBitmapRectToRect(image, &damage, damage);
} }
class DriSurfaceAdapter : public ui::SurfaceOzoneCanvas {
public:
DriSurfaceAdapter(DriWrapper* dri,
const base::WeakPtr<HardwareDisplayController>& controller);
virtual ~DriSurfaceAdapter();
// SurfaceOzoneCanvas:
virtual skia::RefPtr<SkCanvas> GetCanvas() OVERRIDE;
virtual void ResizeCanvas(const gfx::Size& viewport_size) OVERRIDE;
virtual void PresentCanvas(const gfx::Rect& damage) OVERRIDE;
virtual scoped_ptr<gfx::VSyncProvider> CreateVSyncProvider() OVERRIDE;
private:
void UpdateNativeSurface(const gfx::Rect& damage);
DriWrapper* dri_;
scoped_ptr<DriSurface> native_surface_;
skia::RefPtr<SkSurface> surface_;
gfx::Rect last_damage_;
base::WeakPtr<HardwareDisplayController> controller_;
DISALLOW_COPY_AND_ASSIGN(DriSurfaceAdapter);
};
DriSurfaceAdapter::DriSurfaceAdapter(
DriWrapper* dri,
const base::WeakPtr<HardwareDisplayController>& controller)
: dri_(dri), controller_(controller) {
}
DriSurfaceAdapter::~DriSurfaceAdapter() {
}
skia::RefPtr<SkCanvas> DriSurfaceAdapter::GetCanvas() {
return skia::SharePtr(surface_->getCanvas());
}
void DriSurfaceAdapter::ResizeCanvas(const gfx::Size& viewport_size) {
SkImageInfo info = SkImageInfo::MakeN32(
viewport_size.width(), viewport_size.height(), kOpaque_SkAlphaType);
surface_ = skia::AdoptRef(SkSurface::NewRaster(info));
if (controller_) {
// Need to use the mode size rather than |viewport_size| since a display
// cannot scanout from a buffer smaller than the mode.
native_surface_.reset(
new DriSurface(dri_,
gfx::Size(controller_->get_mode().hdisplay,
controller_->get_mode().vdisplay)));
CHECK(native_surface_->Initialize());
}
}
void DriSurfaceAdapter::PresentCanvas(const gfx::Rect& damage) {
CHECK(base::MessageLoopForUI::IsCurrent());
if (!controller_)
return;
UpdateNativeSurface(damage);
controller_->SchedulePageFlip(std::vector<OverlayPlane>(
1, OverlayPlane(native_surface_->backbuffer())));
controller_->WaitForPageFlipEvent();
native_surface_->SwapBuffers();
}
scoped_ptr<gfx::VSyncProvider> DriSurfaceAdapter::CreateVSyncProvider() {
return scoped_ptr<gfx::VSyncProvider>(new DriVSyncProvider(controller_));
}
void DriSurfaceAdapter::UpdateNativeSurface(const gfx::Rect& damage) {
SkCanvas* canvas = native_surface_->GetDrawableForWidget();
// The DriSurface is double buffered, so the current back buffer is
// missing the previous update. Expand damage region.
SkRect real_damage = RectToSkRect(UnionRects(damage, last_damage_));
// Copy damage region.
skia::RefPtr<SkImage> image = skia::AdoptRef(surface_->newImageSnapshot());
image->draw(canvas, &real_damage, real_damage, NULL);
last_damage_ = damage;
}
} // namespace } // namespace
// static // static
const gfx::AcceleratedWidget DriSurfaceFactory::kDefaultWidgetHandle = 1; const gfx::AcceleratedWidget DriSurfaceFactory::kDefaultWidgetHandle = 1;
DriSurfaceFactory::DriSurfaceFactory(DriWrapper* drm, DriSurfaceFactory::DriSurfaceFactory(
ScreenManager* screen_manager) DriWrapper* drm,
ScreenManager* screen_manager)
: drm_(drm), : drm_(drm),
screen_manager_(screen_manager), screen_manager_(screen_manager),
state_(UNINITIALIZED), state_(UNINITIALIZED),
...@@ -190,7 +106,7 @@ scoped_ptr<ui::SurfaceOzoneCanvas> DriSurfaceFactory::CreateCanvasForWidget( ...@@ -190,7 +106,7 @@ scoped_ptr<ui::SurfaceOzoneCanvas> DriSurfaceFactory::CreateCanvasForWidget(
ResetCursor(w); ResetCursor(w);
return scoped_ptr<ui::SurfaceOzoneCanvas>( return scoped_ptr<ui::SurfaceOzoneCanvas>(
new DriSurfaceAdapter(drm_, screen_manager_->GetDisplayController(w))); new DriSurface(drm_, screen_manager_->GetDisplayController(w)));
} }
bool DriSurfaceFactory::LoadEGLGLES2Bindings( bool DriSurfaceFactory::LoadEGLGLES2Bindings(
......
...@@ -16,7 +16,6 @@ namespace ui { ...@@ -16,7 +16,6 @@ namespace ui {
class DriBuffer; class DriBuffer;
class DriWrapper; class DriWrapper;
class HardwareDisplayController;
class ScreenManager; class ScreenManager;
class SurfaceOzoneCanvas; class SurfaceOzoneCanvas;
......
...@@ -98,49 +98,6 @@ TEST_F(DriSurfaceFactoryTest, SuccessfulWidgetRealization) { ...@@ -98,49 +98,6 @@ TEST_F(DriSurfaceFactoryTest, SuccessfulWidgetRealization) {
EXPECT_TRUE(factory_->CreateCanvasForWidget(w)); EXPECT_TRUE(factory_->CreateCanvasForWidget(w));
} }
TEST_F(DriSurfaceFactoryTest, CheckNativeSurfaceContents) {
EXPECT_EQ(ui::SurfaceFactoryOzone::INITIALIZED,
factory_->InitializeHardware());
gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
EXPECT_EQ(ui::DriSurfaceFactory::kDefaultWidgetHandle, w);
scoped_ptr<ui::SurfaceOzoneCanvas> surface =
factory_->CreateCanvasForWidget(w);
surface->ResizeCanvas(
gfx::Size(kDefaultMode.hdisplay, kDefaultMode.vdisplay));
SkPaint paint;
paint.setColor(SK_ColorWHITE);
SkRect rect = SkRect::MakeWH(kDefaultMode.hdisplay / 2,
kDefaultMode.vdisplay / 2);
surface->GetCanvas()->drawRect(rect, paint);
surface->PresentCanvas(
gfx::Rect(0, 0, kDefaultMode.hdisplay / 2, kDefaultMode.vdisplay / 2));
SkBitmap image;
// Buffers 0 and 1 are the cursor buffers, 2 is the modeset buffer, and
// 3 and 4 are the surface buffers.
// Buffer 4 is the backbuffer we just painted in, so we want to make sure its
// contents are correct.
image.setInfo(dri_->buffers()[4]->getCanvas()->imageInfo());
EXPECT_TRUE(dri_->buffers()[4]->getCanvas()->readPixels(&image, 0, 0));
EXPECT_EQ(kDefaultMode.hdisplay, image.width());
EXPECT_EQ(kDefaultMode.vdisplay, image.height());
// Make sure the updates are correctly propagated to the native surface.
for (int i = 0; i < image.height(); ++i) {
for (int j = 0; j < image.width(); ++j) {
if (j < kDefaultMode.hdisplay / 2 && i < kDefaultMode.vdisplay / 2)
EXPECT_EQ(SK_ColorWHITE, image.getColor(j, i));
else
EXPECT_EQ(SK_ColorBLACK, image.getColor(j, i));
}
}
}
TEST_F(DriSurfaceFactoryTest, SetCursorImage) { TEST_F(DriSurfaceFactoryTest, SetCursorImage) {
EXPECT_EQ(ui::SurfaceFactoryOzone::INITIALIZED, EXPECT_EQ(ui::SurfaceFactoryOzone::INITIALIZED,
factory_->InitializeHardware()); factory_->InitializeHardware());
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "base/message_loop/message_loop.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkColor.h"
...@@ -27,6 +28,7 @@ class DriSurfaceTest : public testing::Test { ...@@ -27,6 +28,7 @@ class DriSurfaceTest : public testing::Test {
virtual void TearDown() OVERRIDE; virtual void TearDown() OVERRIDE;
protected: protected:
scoped_ptr<base::MessageLoop> message_loop_;
scoped_ptr<ui::MockDriWrapper> drm_; scoped_ptr<ui::MockDriWrapper> drm_;
scoped_ptr<ui::HardwareDisplayController> controller_; scoped_ptr<ui::HardwareDisplayController> controller_;
scoped_ptr<ui::DriSurface> surface_; scoped_ptr<ui::DriSurface> surface_;
...@@ -36,51 +38,63 @@ class DriSurfaceTest : public testing::Test { ...@@ -36,51 +38,63 @@ class DriSurfaceTest : public testing::Test {
}; };
void DriSurfaceTest::SetUp() { void DriSurfaceTest::SetUp() {
message_loop_.reset(new base::MessageLoopForUI);
drm_.reset(new ui::MockDriWrapper(3)); drm_.reset(new ui::MockDriWrapper(3));
controller_.reset(new ui::HardwareDisplayController(drm_.get(), 1, 1));
surface_.reset(new ui::DriSurface( controller_.reset(new ui::HardwareDisplayController(drm_.get(), 1, 1));
drm_.get(), gfx::Size(kDefaultMode.hdisplay, kDefaultMode.vdisplay))); scoped_refptr<ui::DriBuffer> buffer(new ui::DriBuffer(drm_.get()));
SkImageInfo info = SkImageInfo::MakeN32Premul(kDefaultMode.hdisplay,
kDefaultMode.vdisplay);
EXPECT_TRUE(buffer->Initialize(info));
EXPECT_TRUE(controller_->Modeset(ui::OverlayPlane(buffer), kDefaultMode));
surface_.reset(new ui::DriSurface(drm_.get(), controller_->AsWeakPtr()));
surface_->ResizeCanvas(gfx::Size(kDefaultMode.hdisplay,
kDefaultMode.vdisplay));
} }
void DriSurfaceTest::TearDown() { void DriSurfaceTest::TearDown() {
surface_.reset(); surface_.reset();
controller_.reset(); controller_.reset();
drm_.reset(); drm_.reset();
} message_loop_.reset();
TEST_F(DriSurfaceTest, FailInitialization) {
drm_->set_create_dumb_buffer_expectation(false);
EXPECT_FALSE(surface_->Initialize());
}
TEST_F(DriSurfaceTest, SuccessfulInitialization) {
EXPECT_TRUE(surface_->Initialize());
} }
TEST_F(DriSurfaceTest, CheckFBIDOnSwap) { TEST_F(DriSurfaceTest, CheckFBIDOnSwap) {
EXPECT_TRUE(surface_->Initialize()); surface_->PresentCanvas(gfx::Rect());
// Framebuffer ID 1 is allocated in SetUp for the buffer used to modeset.
// Check that the framebuffer ID is correct. EXPECT_EQ(3u, drm_->current_framebuffer());
EXPECT_EQ(2u, surface_->GetFramebufferId()); surface_->PresentCanvas(gfx::Rect());
EXPECT_EQ(2u, drm_->current_framebuffer());
surface_->SwapBuffers();
EXPECT_EQ(1u, surface_->GetFramebufferId());
} }
TEST_F(DriSurfaceTest, CheckPixelPointerOnSwap) { TEST_F(DriSurfaceTest, CheckSurfaceContents) {
EXPECT_TRUE(surface_->Initialize()); SkPaint paint;
paint.setColor(SK_ColorWHITE);
void* bitmap_pixels1 = surface_->GetDrawableForWidget()->getDevice() SkRect rect = SkRect::MakeWH(kDefaultMode.hdisplay / 2,
->accessBitmap(false).getPixels(); kDefaultMode.vdisplay / 2);
surface_->GetCanvas()->drawRect(rect, paint);
surface_->SwapBuffers(); surface_->PresentCanvas(
gfx::Rect(0, 0, kDefaultMode.hdisplay / 2, kDefaultMode.vdisplay / 2));
void* bitmap_pixels2 = surface_->GetDrawableForWidget()->getDevice()
->accessBitmap(false).getPixels(); SkBitmap image;
// Buffer 0 is the buffer used in SetUp for modesetting and buffer 1 is the
// Check that once the buffers have been swapped the drawable's underlying // frontbuffer.
// pixels have been changed. // Buffer 2 is the backbuffer we just painted in, so we want to make sure its
EXPECT_NE(bitmap_pixels1, bitmap_pixels2); // contents are correct.
image.setInfo(drm_->buffers()[2]->getCanvas()->imageInfo());
EXPECT_TRUE(drm_->buffers()[2]->getCanvas()->readPixels(&image, 0, 0));
EXPECT_EQ(kDefaultMode.hdisplay, image.width());
EXPECT_EQ(kDefaultMode.vdisplay, image.height());
// Make sure the updates are correctly propagated to the native surface.
for (int i = 0; i < image.height(); ++i) {
for (int j = 0; j < image.width(); ++j) {
if (j < kDefaultMode.hdisplay / 2 && i < kDefaultMode.vdisplay / 2)
EXPECT_EQ(SK_ColorWHITE, image.getColor(j, i));
else
EXPECT_EQ(SK_ColorBLACK, image.getColor(j, i));
}
}
} }
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
'gbm_buffer_base.h', 'gbm_buffer_base.h',
'gbm_surface.cc', 'gbm_surface.cc',
'gbm_surface.h', 'gbm_surface.h',
'gbm_surfaceless.cc',
'gbm_surfaceless.h',
'gbm_surface_factory.cc', 'gbm_surface_factory.cc',
'gbm_surface_factory.h', 'gbm_surface_factory.h',
'gpu_platform_support_gbm.cc', 'gpu_platform_support_gbm.cc',
......
...@@ -7,11 +7,9 @@ ...@@ -7,11 +7,9 @@
#include <gbm.h> #include <gbm.h>
#include "base/logging.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_buffer.h"
#include "ui/ozone/platform/dri/dri_wrapper.h" #include "ui/ozone/platform/dri/dri_wrapper.h"
#include "ui/ozone/platform/dri/gbm_buffer_base.h" #include "ui/ozone/platform/dri/gbm_buffer_base.h"
#include "ui/ozone/platform/dri/hardware_display_controller.h"
#include "ui/ozone/platform/dri/scanout_buffer.h" #include "ui/ozone/platform/dri/scanout_buffer.h"
namespace ui { namespace ui {
...@@ -75,25 +73,19 @@ void GbmSurfaceBuffer::Destroy(gbm_bo* buffer, void* data) { ...@@ -75,25 +73,19 @@ void GbmSurfaceBuffer::Destroy(gbm_bo* buffer, void* data) {
} // namespace } // namespace
GbmSurface::GbmSurface(gbm_device* device, GbmSurface::GbmSurface(
DriWrapper* dri, const base::WeakPtr<HardwareDisplayController>& controller,
const gfx::Size& size) gbm_device* device,
: gbm_device_(device), DriWrapper* dri)
: GbmSurfaceless(controller),
gbm_device_(device),
dri_(dri), dri_(dri),
size_(size),
native_surface_(NULL), native_surface_(NULL),
buffers_(), current_buffer_(NULL) {}
front_buffer_(0) {
for (size_t i = 0; i < arraysize(buffers_); ++i)
buffers_[i] = NULL;
}
GbmSurface::~GbmSurface() { GbmSurface::~GbmSurface() {
for (size_t i = 0; i < arraysize(buffers_); ++i) { if (current_buffer_)
if (buffers_[i]) { gbm_surface_release_buffer(native_surface_, current_buffer_);
gbm_surface_release_buffer(native_surface_, buffers_[i]->bo());
}
}
if (native_surface_) if (native_surface_)
gbm_surface_destroy(native_surface_); gbm_surface_destroy(native_surface_);
...@@ -103,73 +95,51 @@ bool GbmSurface::Initialize() { ...@@ -103,73 +95,51 @@ bool GbmSurface::Initialize() {
// TODO(dnicoara) Check underlying system support for pixel format. // TODO(dnicoara) Check underlying system support for pixel format.
native_surface_ = gbm_surface_create( native_surface_ = gbm_surface_create(
gbm_device_, gbm_device_,
size_.width(), controller_->get_mode().hdisplay,
size_.height(), controller_->get_mode().vdisplay,
GBM_BO_FORMAT_XRGB8888, GBM_BO_FORMAT_XRGB8888,
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
if (!native_surface_) if (!native_surface_)
return false; return false;
dumb_buffer_ = new DriBuffer(dri_);
if (!dumb_buffer_->Initialize(SkImageInfo::MakeN32Premul(size_.width(),
size_.height())))
return false;
return true; return true;
} }
uint32_t GbmSurface::GetFramebufferId() const { intptr_t GbmSurface::GetNativeWindow() {
if (!buffers_[front_buffer_ ^ 1]) CHECK(native_surface_);
return dumb_buffer_->GetFramebufferId(); return reinterpret_cast<intptr_t>(native_surface_);
return buffers_[front_buffer_ ^ 1]->GetFramebufferId();
} }
uint32_t GbmSurface::GetHandle() const { bool GbmSurface::OnSwapBuffers() {
if (!buffers_[front_buffer_ ^ 1]) CHECK(native_surface_);
return dumb_buffer_->GetHandle();
return buffers_[front_buffer_ ^ 1]->GetHandle();
}
gfx::Size GbmSurface::Size() const { if (!controller_)
return size_; return false;
}
// Before scheduling the backbuffer to be scanned out we need to "lock" it. gbm_bo* pending_buffer = gbm_surface_lock_front_buffer(native_surface_);
// When we lock it, GBM will give a pointer to a buffer representing the scoped_refptr<GbmSurfaceBuffer> primary =
// backbuffer. It will also update its information on which buffers can not be GbmSurfaceBuffer::GetBuffer(pending_buffer);
// used for drawing. The buffer will be released when the page flip event if (!primary) {
// occurs (see SwapBuffers). This is called from HardwareDisplayController primary = GbmSurfaceBuffer::CreateBuffer(dri_, pending_buffer);
// before scheduling a page flip. if (!primary) {
void GbmSurface::PreSwapBuffers() { LOG(ERROR) << "Failed to associate the buffer with the controller";
CHECK(native_surface_); return false;
// Lock the buffer we want to display. }
gbm_bo* bo = gbm_surface_lock_front_buffer(native_surface_);
buffers_[front_buffer_ ^ 1] = GbmSurfaceBuffer::GetBuffer(bo);
// 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 (!buffers_[front_buffer_ ^ 1]) {
buffers_[front_buffer_ ^ 1] = GbmSurfaceBuffer::CreateBuffer(dri_, bo);
DCHECK(buffers_[front_buffer_ ^ 1])
<< "Failed to associate the buffer with the controller";
} }
}
void GbmSurface::SwapBuffers() { // The primary buffer is a special case.
// If there was a frontbuffer, is no longer active. Release it back to GBM. queued_planes_.push_back(OverlayPlane(primary));
if (buffers_[front_buffer_])
gbm_surface_release_buffer(native_surface_, buffers_[front_buffer_]->bo()); if (!GbmSurfaceless::OnSwapBuffers())
return false;
// Update the index to the frontbuffer.
front_buffer_ ^= 1; // If there was a frontbuffer, it is no longer active. Release it back to GBM.
// We've just released it. Since GBM doesn't guarantee we'll get the same if (current_buffer_)
// buffer back, we set it to NULL so we don't keep track of objects that may gbm_surface_release_buffer(native_surface_, current_buffer_);
// have been destroyed.
buffers_[front_buffer_ ^ 1] = NULL; current_buffer_ = pending_buffer;
return true;
} }
} // namespace ui } // namespace ui
...@@ -8,7 +8,8 @@ ...@@ -8,7 +8,8 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
#include "ui/ozone/platform/dri/scanout_surface.h" #include "ui/ozone/platform/dri/gbm_surfaceless.h"
#include "ui/ozone/public/surface_ozone_egl.h"
struct gbm_bo; struct gbm_bo;
struct gbm_device; struct gbm_device;
...@@ -18,52 +19,34 @@ namespace ui { ...@@ -18,52 +19,34 @@ namespace ui {
class DriBuffer; class DriBuffer;
class DriWrapper; class DriWrapper;
class GbmBufferBase;
// Implement the ScanoutSurface interface on top of GBM (Generic Buffer // Extends the GBM surfaceless functionality and adds an implicit surface for
// Manager). GBM provides generic access to hardware accelerated surfaces which // the primary plane. Arbitrary buffers can still be allocated and displayed as
// can be used in association with EGL to provide accelerated drawing. // overlay planes, however the primary plane is associated with the native
class GbmSurface : public ScanoutSurface { // surface and is updated via an EGLSurface.
class GbmSurface : public GbmSurfaceless {
public: public:
GbmSurface(gbm_device* device, DriWrapper* dri, const gfx::Size& size); GbmSurface(const base::WeakPtr<HardwareDisplayController>& controller,
gbm_device* device,
DriWrapper* dri);
virtual ~GbmSurface(); virtual ~GbmSurface();
scoped_refptr<GbmBufferBase> backbuffer() const { bool Initialize();
return buffers_[front_buffer_ ^ 1];
}
// ScanoutSurface: // GbmSurfaceless:
virtual bool Initialize() OVERRIDE; virtual intptr_t GetNativeWindow() OVERRIDE;
virtual uint32_t GetFramebufferId() const OVERRIDE; virtual bool OnSwapBuffers() OVERRIDE;
virtual uint32_t GetHandle() const OVERRIDE;
virtual gfx::Size Size() const OVERRIDE;
virtual void PreSwapBuffers() OVERRIDE;
virtual void SwapBuffers() OVERRIDE;
gbm_surface* native_surface() { return native_surface_; };
private: private:
gbm_device* gbm_device_; gbm_device* gbm_device_;
DriWrapper* dri_; DriWrapper* dri_;
gfx::Size size_;
// The native GBM surface. In EGL this represents the EGLNativeWindowType. // The native GBM surface. In EGL this represents the EGLNativeWindowType.
gbm_surface* native_surface_; gbm_surface* native_surface_;
// Backing GBM buffers. One is the current front buffer. The other is the // Buffer currently used for scanout.
// current backbuffer that is pending scan out. gbm_bo* current_buffer_;
scoped_refptr<GbmBufferBase> 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_refptr<DriBuffer> dumb_buffer_;
DISALLOW_COPY_AND_ASSIGN(GbmSurface); DISALLOW_COPY_AND_ASSIGN(GbmSurface);
}; };
......
...@@ -8,127 +8,15 @@ ...@@ -8,127 +8,15 @@
#include <gbm.h> #include <gbm.h>
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "ui/ozone/platform/dri/dri_vsync_provider.h"
#include "ui/ozone/platform/dri/gbm_buffer.h" #include "ui/ozone/platform/dri/gbm_buffer.h"
#include "ui/ozone/platform/dri/gbm_surface.h" #include "ui/ozone/platform/dri/gbm_surface.h"
#include "ui/ozone/platform/dri/hardware_display_controller.h" #include "ui/ozone/platform/dri/gbm_surfaceless.h"
#include "ui/ozone/platform/dri/scanout_surface.h"
#include "ui/ozone/platform/dri/screen_manager.h" #include "ui/ozone/platform/dri/screen_manager.h"
#include "ui/ozone/public/native_pixmap.h" #include "ui/ozone/public/native_pixmap.h"
#include "ui/ozone/public/surface_ozone_egl.h" #include "ui/ozone/public/surface_ozone_egl.h"
namespace ui { namespace ui {
namespace {
class GbmSurfaceAdapter : public ui::SurfaceOzoneEGL {
public:
GbmSurfaceAdapter(
gbm_device* device,
DriWrapper* dri,
const base::WeakPtr<HardwareDisplayController>& controller);
virtual ~GbmSurfaceAdapter();
bool Initialize();
// 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;
virtual bool ScheduleOverlayPlane(int plane_z_order,
gfx::OverlayTransform plane_transform,
scoped_refptr<ui::NativePixmap> buffer,
const gfx::Rect& display_bounds,
const gfx::RectF& crop_rect) OVERRIDE;
private:
gbm_device* device_;
DriWrapper* dri_;
scoped_ptr<GbmSurface> surface_;
base::WeakPtr<HardwareDisplayController> controller_;
OverlayPlaneList overlays_;
DISALLOW_COPY_AND_ASSIGN(GbmSurfaceAdapter);
};
GbmSurfaceAdapter::GbmSurfaceAdapter(
gbm_device* device,
DriWrapper* dri,
const base::WeakPtr<HardwareDisplayController>& controller)
: device_(device), dri_(dri), controller_(controller) {}
GbmSurfaceAdapter::~GbmSurfaceAdapter() {}
bool GbmSurfaceAdapter::Initialize() {
if (controller_) {
surface_.reset(
new GbmSurface(device_,
dri_,
gfx::Size(controller_->get_mode().hdisplay,
controller_->get_mode().vdisplay)));
return surface_->Initialize();
}
return false;
}
intptr_t GbmSurfaceAdapter::GetNativeWindow() {
if (!controller_)
return 0;
return reinterpret_cast<intptr_t>(surface_->native_surface());
}
bool GbmSurfaceAdapter::ResizeNativeWindow(const gfx::Size& viewport_size) {
return true;
}
bool GbmSurfaceAdapter::OnSwapBuffers() {
if (!controller_)
return false;
if (surface_) {
surface_->PreSwapBuffers();
overlays_.push_back(OverlayPlane(surface_->backbuffer()));
}
bool flip_succeeded = controller_->SchedulePageFlip(overlays_);
overlays_.clear();
if (flip_succeeded)
controller_->WaitForPageFlipEvent();
if (surface_)
surface_->SwapBuffers();
return flip_succeeded;
}
bool GbmSurfaceAdapter::ScheduleOverlayPlane(
int plane_z_order,
gfx::OverlayTransform plane_transform,
scoped_refptr<NativePixmap> buffer,
const gfx::Rect& display_bounds,
const gfx::RectF& crop_rect) {
GbmPixmap* pixmap = static_cast<GbmPixmap*>(buffer.get());
if (!pixmap) {
LOG(ERROR) << "ScheduleOverlayPlane passed NULL buffer";
return false;
}
overlays_.push_back(OverlayPlane(pixmap->buffer(),
plane_z_order,
plane_transform,
display_bounds,
crop_rect));
return true;
}
scoped_ptr<gfx::VSyncProvider> GbmSurfaceAdapter::CreateVSyncProvider() {
return scoped_ptr<gfx::VSyncProvider>(new DriVSyncProvider(controller_));
}
} // namespace
GbmSurfaceFactory::GbmSurfaceFactory(bool allow_surfaceless) GbmSurfaceFactory::GbmSurfaceFactory(bool allow_surfaceless)
: DriSurfaceFactory(NULL, NULL), : DriSurfaceFactory(NULL, NULL),
device_(NULL), device_(NULL),
...@@ -204,19 +92,24 @@ bool GbmSurfaceFactory::LoadEGLGLES2Bindings( ...@@ -204,19 +92,24 @@ bool GbmSurfaceFactory::LoadEGLGLES2Bindings(
return true; return true;
} }
scoped_ptr<ui::SurfaceOzoneEGL> GbmSurfaceFactory::CreateEGLSurfaceForWidget( scoped_ptr<SurfaceOzoneEGL> GbmSurfaceFactory::CreateEGLSurfaceForWidget(
gfx::AcceleratedWidget w) { gfx::AcceleratedWidget widget) {
CHECK(state_ == INITIALIZED); CHECK(state_ == INITIALIZED);
ResetCursor(w); ResetCursor(widget);
scoped_ptr<GbmSurfaceAdapter> surface( if (allow_surfaceless_) {
new GbmSurfaceAdapter(device_, return scoped_ptr<SurfaceOzoneEGL>(
drm_, new GbmSurfaceless(screen_manager_->GetDisplayController(widget)));
screen_manager_->GetDisplayController(w))); } else {
if (!allow_surfaceless_ && !surface->Initialize()) scoped_ptr<GbmSurface> surface(
return scoped_ptr<SurfaceOzoneEGL>(); new GbmSurface(screen_manager_->GetDisplayController(widget),
device_,
return surface.PassAs<SurfaceOzoneEGL>(); drm_));
if (!surface->Initialize())
return scoped_ptr<SurfaceOzoneEGL>();
return surface.PassAs<SurfaceOzoneEGL>();
}
} }
scoped_refptr<ui::NativePixmap> GbmSurfaceFactory::CreateNativePixmap( scoped_refptr<ui::NativePixmap> GbmSurfaceFactory::CreateNativePixmap(
......
// 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_surfaceless.h"
#include "ui/ozone/platform/dri/dri_vsync_provider.h"
#include "ui/ozone/platform/dri/gbm_buffer.h"
namespace ui {
GbmSurfaceless::GbmSurfaceless(
const base::WeakPtr<HardwareDisplayController>& controller)
: controller_(controller) {}
GbmSurfaceless::~GbmSurfaceless() {}
intptr_t GbmSurfaceless::GetNativeWindow() {
NOTREACHED();
return 0;
}
bool GbmSurfaceless::ResizeNativeWindow(const gfx::Size& viewport_size) {
NOTIMPLEMENTED();
return false;
}
bool GbmSurfaceless::OnSwapBuffers() {
if (!controller_)
return false;
bool success = controller_->SchedulePageFlip(queued_planes_);
queued_planes_.clear();
if (success)
controller_->WaitForPageFlipEvent();
return success;
}
scoped_ptr<gfx::VSyncProvider> GbmSurfaceless::CreateVSyncProvider() {
return scoped_ptr<gfx::VSyncProvider>(new DriVSyncProvider(controller_));
}
bool GbmSurfaceless::ScheduleOverlayPlane(
int plane_z_order,
gfx::OverlayTransform plane_transform,
scoped_refptr<ui::NativePixmap> buffer,
const gfx::Rect& display_bounds,
const gfx::RectF& crop_rect) {
scoped_refptr<GbmPixmap> pixmap =
static_cast<GbmPixmap*>(buffer.get());
if (!pixmap) {
LOG(ERROR) << "ScheduleOverlayPlane passed NULL buffer.";
return false;
}
queued_planes_.push_back(OverlayPlane(pixmap->buffer(),
plane_z_order,
plane_transform,
display_bounds,
crop_rect));
return true;
}
} // namespace ui
// 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_SURFACELESS_H_
#define UI_OZONE_PLATFORM_DRI_GBM_SURFACELESS_H_
#include "base/memory/scoped_ptr.h"
#include "ui/ozone/platform/dri/hardware_display_controller.h"
#include "ui/ozone/public/surface_ozone_egl.h"
namespace gfx {
class Size;
class Rect;
} // namespace gfx
namespace ui {
// In surfaceless mode drawing and displaying happens directly through
// NativePixmap buffers. CC would call into SurfaceFactoryOzone to allocate the
// buffers and then call ScheduleOverlayPlane(..) to schedule the buffer for
// presentation.
class GbmSurfaceless : public SurfaceOzoneEGL {
public:
GbmSurfaceless(const base::WeakPtr<HardwareDisplayController>& controller);
virtual ~GbmSurfaceless();
// 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;
virtual bool ScheduleOverlayPlane(int plane_z_order,
gfx::OverlayTransform plane_transform,
scoped_refptr<ui::NativePixmap> buffer,
const gfx::Rect& display_bounds,
const gfx::RectF& crop_rect) OVERRIDE;
protected:
base::WeakPtr<HardwareDisplayController> controller_;
OverlayPlaneList queued_planes_;
DISALLOW_COPY_AND_ASSIGN(GbmSurfaceless);
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_DRI_GBM_SURFACELESS_H_
// 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;
// Prepare the surface to be displayed.
virtual void PreSwapBuffers() = 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_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment