| Index: ui/gfx/ozone/dri/gbm_surface.cc
|
| diff --git a/ui/gfx/ozone/dri/gbm_surface.cc b/ui/gfx/ozone/dri/gbm_surface.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a3b33c69002cb8f8b55c963970ea5331ea1b358b
|
| --- /dev/null
|
| +++ b/ui/gfx/ozone/dri/gbm_surface.cc
|
| @@ -0,0 +1,173 @@
|
| +// Copyright 2013 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "ui/gfx/ozone/dri/gbm_surface.h"
|
| +
|
| +#include "base/logging.h"
|
| +#include "third_party/mesa/src/src/gbm/main/gbm.h"
|
| +#include "ui/gfx/ozone/dri/hardware_display_controller.h"
|
| +
|
| +namespace gfx {
|
| +
|
| +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 with the
|
| + // controller. 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(HardwareDisplayController* controller,
|
| + 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 get_framebuffer() const { return framebuffer_; }
|
| +
|
| + private:
|
| + BufferData(HardwareDisplayController* controller);
|
| +
|
| + ~BufferData();
|
| +
|
| + HardwareDisplayController* controller_;
|
| +
|
| + // 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(HardwareDisplayController* controller)
|
| + : controller_(controller),
|
| + framebuffer_(0) {
|
| +}
|
| +
|
| +BufferData::~BufferData() {
|
| + if (framebuffer_)
|
| + controller_->RemoveFramebuffer(framebuffer_);
|
| +}
|
| +
|
| +// static
|
| +BufferData* BufferData::CreateData(HardwareDisplayController* controller,
|
| + gbm_bo* buffer) {
|
| + uint32_t handle = gbm_bo_get_handle(buffer).u32;
|
| + uint32_t stride = gbm_bo_get_stride(buffer);
|
| +
|
| + BufferData* data = new BufferData(controller);
|
| + // 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 (!controller->AddFramebuffer(kColorDepth,
|
| + kPixelDepth,
|
| + stride,
|
| + handle,
|
| + &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(HardwareDisplayController* controller,
|
| + gbm_device* device)
|
| + : controller_(controller),
|
| + gbm_device_(device),
|
| + native_surface_(NULL),
|
| + buffers_(),
|
| + front_buffer_(0) {
|
| + for (int i = 0; i < 2; ++i)
|
| + buffers_[i] = NULL;
|
| +}
|
| +
|
| +GbmSurface::~GbmSurface() {
|
| + for (int i = 0; i < 2; ++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_,
|
| + controller_->get_mode().hdisplay,
|
| + controller_->get_mode().vdisplay,
|
| + GBM_BO_FORMAT_XRGB8888,
|
| + GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
|
| +
|
| + if (!native_surface_)
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +uint32_t GbmSurface::GetFramebufferId() const {
|
| + BufferData* data = BufferData::GetData(buffers_[front_buffer_ ^ 1]);
|
| + return data->get_framebuffer();
|
| +}
|
| +
|
| +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() {
|
| + // 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 with the |controller_|.
|
| + if (data == NULL) {
|
| + data = BufferData::CreateData(controller_, buffers_[front_buffer_ ^ 1]);
|
| + DCHECK(data) << "Failed to associate the buffer with the controller";
|
| + }
|
| +}
|
| +
|
| +} // namespace gfx
|
|
|