Commit f682ca9a authored by dnicoara@chromium.org's avatar dnicoara@chromium.org

[Ozone-GBM] Migrate GBM buffers to use the ScanoutBuffer interface

BUG=none
NOTRY=true

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@284217 0039d316-1c4b-4281-b951-d872f2087c98
parent 76d70f6b
// 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/buffer_data.h"
#include <gbm.h>
#include "base/logging.h"
#include "ui/ozone/platform/dri/dri_wrapper.h"
namespace ui {
// Pixel configuration for the current buffer format.
// TODO(dnicoara) These will need to change once we query the hardware for
// supported configurations.
const uint8_t kColorDepth = 24;
const uint8_t kPixelDepth = 32;
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 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_BUFFER_DATA_H_
#define UI_OZONE_PLATFORM_DRI_BUFFER_DATA_H_
#include "base/memory/scoped_ptr.h"
struct gbm_bo;
namespace ui {
class DriWrapper;
// This class is used to tag a gbm buffer with custom information needed
// for presentation with the surface factory.
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 destroy 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);
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_DRI_BUFFER_DATA_H_
...@@ -29,14 +29,14 @@ ...@@ -29,14 +29,14 @@
'OZONE_IMPLEMENTATION', 'OZONE_IMPLEMENTATION',
], ],
'sources': [ 'sources': [
'buffer_data.cc',
'buffer_data.h',
'chromeos/display_message_handler.cc', 'chromeos/display_message_handler.cc',
'chromeos/display_message_handler.h', 'chromeos/display_message_handler.h',
'chromeos/native_display_delegate_proxy.cc', 'chromeos/native_display_delegate_proxy.cc',
'chromeos/native_display_delegate_proxy.h', 'chromeos/native_display_delegate_proxy.h',
'gbm_buffer.cc', 'gbm_buffer.cc',
'gbm_buffer.h', 'gbm_buffer.h',
'gbm_buffer_base.cc',
'gbm_buffer_base.h',
'gbm_surface.cc', 'gbm_surface.cc',
'gbm_surface.h', 'gbm_surface.h',
'gbm_surface_factory.cc', 'gbm_surface_factory.cc',
......
// 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_buffer_base.h"
#include <gbm.h>
#include "base/logging.h"
#include "ui/ozone/platform/dri/dri_wrapper.h"
namespace ui {
namespace {
// Pixel configuration for the current buffer format.
// TODO(dnicoara) These will need to change once we query the hardware for
// supported configurations.
const uint8_t kColorDepth = 24;
const uint8_t kPixelDepth = 32;
} // namespace
GbmBufferBase::GbmBufferBase(DriWrapper* dri, gbm_bo* bo, bool scanout)
: dri_(dri), bo_(bo), framebuffer_(0) {
if (scanout && !dri_->AddFramebuffer(gbm_bo_get_width(bo),
gbm_bo_get_height(bo),
kColorDepth,
kPixelDepth,
gbm_bo_get_stride(bo),
gbm_bo_get_handle(bo).u32,
&framebuffer_))
LOG(ERROR) << "Failed to register buffer";
}
GbmBufferBase::~GbmBufferBase() {
if (framebuffer_)
dri_->RemoveFramebuffer(framebuffer_);
}
uint32_t GbmBufferBase::GetFramebufferId() const {
return framebuffer_;
}
uint32_t GbmBufferBase::GetHandle() const {
return gbm_bo_get_handle(bo_).u32;
}
gfx::Size GbmBufferBase::GetSize() const {
return gfx::Size(gbm_bo_get_width(bo_), gbm_bo_get_height(bo_));
}
} // 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_BUFFER_BASE_H_
#define UI_OZONE_PLATFORM_DRI_GBM_BUFFER_BASE_H_
#include "ui/ozone/platform/dri/scanout_buffer.h"
struct gbm_bo;
namespace ui {
class DriWrapper;
// Wrapper for a GBM buffer. The base class provides common functionality
// required to prepare the buffer for scanout. It does not provide any ownership
// of the buffer. Implementations of this base class should deal with buffer
// ownership.
class GbmBufferBase : public ScanoutBuffer {
public:
gbm_bo* bo() const { return bo_; }
// ScanoutBuffer:
virtual uint32_t GetFramebufferId() const OVERRIDE;
virtual uint32_t GetHandle() const OVERRIDE;
virtual gfx::Size GetSize() const OVERRIDE;
protected:
GbmBufferBase(DriWrapper* dri, gbm_bo* bo, bool scanout);
virtual ~GbmBufferBase();
private:
DriWrapper* dri_;
gbm_bo* bo_;
uint32_t framebuffer_;
DISALLOW_COPY_AND_ASSIGN(GbmBufferBase);
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_DRI_GBM_BUFFER_BASE_H_
...@@ -8,13 +8,73 @@ ...@@ -8,13 +8,73 @@
#include "base/logging.h" #include "base/logging.h"
#include "third_party/skia/include/core/SkImageInfo.h" #include "third_party/skia/include/core/SkImageInfo.h"
#include "ui/ozone/platform/dri/buffer_data.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/hardware_display_controller.h" #include "ui/ozone/platform/dri/hardware_display_controller.h"
#include "ui/ozone/platform/dri/scanout_buffer.h"
namespace ui { namespace ui {
namespace {
class GbmSurfaceBuffer : public GbmBufferBase {
public:
static scoped_refptr<GbmSurfaceBuffer> CreateBuffer(DriWrapper* dri,
gbm_bo* buffer);
static scoped_refptr<GbmSurfaceBuffer> GetBuffer(gbm_bo* buffer);
private:
GbmSurfaceBuffer(DriWrapper* dri, gbm_bo* bo);
virtual ~GbmSurfaceBuffer();
static void Destroy(gbm_bo* buffer, void* data);
// This buffer is special and is released by GBM at any point in time (as
// long as it isn't being used). Since GBM should be the only one to
// release this buffer, keep a self-reference in order to keep this alive.
// When GBM calls Destroy(..) the self-reference will dissapear and this will
// be destroyed.
scoped_refptr<GbmSurfaceBuffer> self_;
DISALLOW_COPY_AND_ASSIGN(GbmSurfaceBuffer);
};
GbmSurfaceBuffer::GbmSurfaceBuffer(DriWrapper* dri, gbm_bo* bo)
: GbmBufferBase(dri, bo, true) {
if (GetFramebufferId()) {
self_ = this;
gbm_bo_set_user_data(bo, this, GbmSurfaceBuffer::Destroy);
}
}
GbmSurfaceBuffer::~GbmSurfaceBuffer() {}
// static
scoped_refptr<GbmSurfaceBuffer> GbmSurfaceBuffer::CreateBuffer(
DriWrapper* dri, gbm_bo* buffer) {
scoped_refptr<GbmSurfaceBuffer> scoped_buffer(new GbmSurfaceBuffer(dri,
buffer));
if (!scoped_buffer->GetFramebufferId())
return NULL;
return scoped_buffer;
}
// static
scoped_refptr<GbmSurfaceBuffer> GbmSurfaceBuffer::GetBuffer(gbm_bo* buffer) {
return scoped_refptr<GbmSurfaceBuffer>(
static_cast<GbmSurfaceBuffer*>(gbm_bo_get_user_data(buffer)));
}
// static
void GbmSurfaceBuffer::Destroy(gbm_bo* buffer, void* data) {
GbmSurfaceBuffer* scoped_buffer = static_cast<GbmSurfaceBuffer*>(data);
scoped_buffer->self_ = NULL;
}
} // namespace
GbmSurface::GbmSurface(gbm_device* device, GbmSurface::GbmSurface(gbm_device* device,
DriWrapper* dri, DriWrapper* dri,
const gfx::Size& size) const gfx::Size& size)
...@@ -31,7 +91,7 @@ GbmSurface::GbmSurface(gbm_device* device, ...@@ -31,7 +91,7 @@ GbmSurface::GbmSurface(gbm_device* device,
GbmSurface::~GbmSurface() { GbmSurface::~GbmSurface() {
for (size_t i = 0; i < arraysize(buffers_); ++i) { for (size_t i = 0; i < arraysize(buffers_); ++i) {
if (buffers_[i]) { if (buffers_[i]) {
gbm_surface_release_buffer(native_surface_, buffers_[i]); gbm_surface_release_buffer(native_surface_, buffers_[i]->bo());
} }
} }
...@@ -63,18 +123,14 @@ uint32_t GbmSurface::GetFramebufferId() const { ...@@ -63,18 +123,14 @@ uint32_t GbmSurface::GetFramebufferId() const {
if (!buffers_[front_buffer_ ^ 1]) if (!buffers_[front_buffer_ ^ 1])
return dumb_buffer_->GetFramebufferId(); return dumb_buffer_->GetFramebufferId();
BufferData* data = BufferData::GetData(buffers_[front_buffer_ ^ 1]); return buffers_[front_buffer_ ^ 1]->GetFramebufferId();
CHECK(data);
return data->framebuffer();
} }
uint32_t GbmSurface::GetHandle() const { uint32_t GbmSurface::GetHandle() const {
if (!buffers_[front_buffer_ ^ 1]) if (!buffers_[front_buffer_ ^ 1])
return dumb_buffer_->GetHandle(); return dumb_buffer_->GetHandle();
BufferData* data = BufferData::GetData(buffers_[front_buffer_ ^ 1]); return buffers_[front_buffer_ ^ 1]->GetHandle();
CHECK(data);
return data->handle();
} }
gfx::Size GbmSurface::Size() const { gfx::Size GbmSurface::Size() const {
...@@ -90,22 +146,23 @@ gfx::Size GbmSurface::Size() const { ...@@ -90,22 +146,23 @@ gfx::Size GbmSurface::Size() const {
void GbmSurface::PreSwapBuffers() { void GbmSurface::PreSwapBuffers() {
CHECK(native_surface_); CHECK(native_surface_);
// Lock the buffer we want to display. // Lock the buffer we want to display.
buffers_[front_buffer_ ^ 1] = gbm_surface_lock_front_buffer(native_surface_); gbm_bo* bo = gbm_surface_lock_front_buffer(native_surface_);
BufferData* data = BufferData::GetData(buffers_[front_buffer_ ^ 1]); buffers_[front_buffer_ ^ 1] = GbmSurfaceBuffer::GetBuffer(bo);
// If it is a new buffer, it won't have any data associated with it. So we // 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 // create it. On creation it will associate itself with the buffer and
// register the buffer. // register the buffer.
if (!data) { if (!buffers_[front_buffer_ ^ 1]) {
data = BufferData::CreateData(dri_, buffers_[front_buffer_ ^ 1]); buffers_[front_buffer_ ^ 1] = GbmSurfaceBuffer::CreateBuffer(dri_, bo);
DCHECK(data) << "Failed to associate the buffer with the controller"; DCHECK(buffers_[front_buffer_ ^ 1])
<< "Failed to associate the buffer with the controller";
} }
} }
void GbmSurface::SwapBuffers() { void GbmSurface::SwapBuffers() {
// If there was a frontbuffer, is no longer active. Release it back to GBM. // If there was a frontbuffer, is no longer active. Release it back to GBM.
if (buffers_[front_buffer_]) if (buffers_[front_buffer_])
gbm_surface_release_buffer(native_surface_, buffers_[front_buffer_]); gbm_surface_release_buffer(native_surface_, buffers_[front_buffer_]->bo());
// Update the index to the frontbuffer. // Update the index to the frontbuffer.
front_buffer_ ^= 1; front_buffer_ ^= 1;
......
...@@ -18,6 +18,7 @@ namespace ui { ...@@ -18,6 +18,7 @@ namespace ui {
class DriBuffer; class DriBuffer;
class DriWrapper; class DriWrapper;
class GbmBufferBase;
// Implement the ScanoutSurface interface on top of GBM (Generic Buffer // Implement the ScanoutSurface interface on top of GBM (Generic Buffer
// Manager). GBM provides generic access to hardware accelerated surfaces which // Manager). GBM provides generic access to hardware accelerated surfaces which
...@@ -49,7 +50,7 @@ class GbmSurface : public ScanoutSurface { ...@@ -49,7 +50,7 @@ class GbmSurface : public ScanoutSurface {
// Backing GBM buffers. One is the current front buffer. The other is the // Backing GBM buffers. One is the current front buffer. The other is the
// current backbuffer that is pending scan out. // current backbuffer that is pending scan out.
gbm_bo* buffers_[2]; scoped_refptr<GbmBufferBase> buffers_[2];
// Index to the front buffer. // Index to the front buffer.
int front_buffer_; int front_buffer_;
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#include <gbm.h> #include <gbm.h>
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "ui/ozone/platform/dri/buffer_data.h"
#include "ui/ozone/platform/dri/dri_vsync_provider.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"
......
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