| Index: ui/ozone/platform/drm/gpu/gbm_surface.cc
|
| diff --git a/ui/ozone/platform/drm/gpu/gbm_surface.cc b/ui/ozone/platform/drm/gpu/gbm_surface.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..08a32f44d7bf7c9c09fc83a49151deaaeb11bb5e
|
| --- /dev/null
|
| +++ b/ui/ozone/platform/drm/gpu/gbm_surface.cc
|
| @@ -0,0 +1,179 @@
|
| +// 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/drm/gpu/gbm_surface.h"
|
| +
|
| +#include <gbm.h>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/logging.h"
|
| +#include "ui/ozone/platform/drm/gpu/drm_buffer.h"
|
| +#include "ui/ozone/platform/drm/gpu/drm_window.h"
|
| +#include "ui/ozone/platform/drm/gpu/gbm_buffer_base.h"
|
| +#include "ui/ozone/platform/drm/gpu/gbm_device.h"
|
| +#include "ui/ozone/platform/drm/gpu/hardware_display_controller.h"
|
| +#include "ui/ozone/platform/drm/gpu/scanout_buffer.h"
|
| +
|
| +namespace ui {
|
| +
|
| +namespace {
|
| +
|
| +void DoNothing(gfx::SwapResult) {
|
| +}
|
| +
|
| +class GbmSurfaceBuffer : public GbmBufferBase {
|
| + public:
|
| + static scoped_refptr<GbmSurfaceBuffer> CreateBuffer(
|
| + const scoped_refptr<DrmDevice>& drm,
|
| + gbm_bo* buffer);
|
| + static scoped_refptr<GbmSurfaceBuffer> GetBuffer(gbm_bo* buffer);
|
| +
|
| + private:
|
| + GbmSurfaceBuffer(const scoped_refptr<DrmDevice>& drm, gbm_bo* bo);
|
| + ~GbmSurfaceBuffer() override;
|
| +
|
| + 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(const scoped_refptr<DrmDevice>& drm,
|
| + gbm_bo* bo)
|
| + : GbmBufferBase(drm, bo, true) {
|
| + if (GetFramebufferId()) {
|
| + self_ = this;
|
| + gbm_bo_set_user_data(bo, this, GbmSurfaceBuffer::Destroy);
|
| + }
|
| +}
|
| +
|
| +GbmSurfaceBuffer::~GbmSurfaceBuffer() {
|
| +}
|
| +
|
| +// static
|
| +scoped_refptr<GbmSurfaceBuffer> GbmSurfaceBuffer::CreateBuffer(
|
| + const scoped_refptr<DrmDevice>& drm,
|
| + gbm_bo* buffer) {
|
| + scoped_refptr<GbmSurfaceBuffer> scoped_buffer(
|
| + new GbmSurfaceBuffer(drm, 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(DrmWindow* window_delegate,
|
| + const scoped_refptr<GbmDevice>& gbm)
|
| + : GbmSurfaceless(window_delegate, NULL),
|
| + gbm_(gbm),
|
| + native_surface_(NULL),
|
| + current_buffer_(NULL),
|
| + weak_factory_(this) {
|
| +}
|
| +
|
| +GbmSurface::~GbmSurface() {
|
| + if (current_buffer_)
|
| + gbm_surface_release_buffer(native_surface_, current_buffer_);
|
| +
|
| + if (native_surface_)
|
| + gbm_surface_destroy(native_surface_);
|
| +}
|
| +
|
| +bool GbmSurface::Initialize() {
|
| + // If we're initializing the surface without a controller (possible on startup
|
| + // where the surface creation can happen before the native window delegate
|
| + // IPCs arrive), initialize the size to a valid value such that surface
|
| + // creation doesn't fail.
|
| + gfx::Size size(1, 1);
|
| + if (window_delegate_->GetController()) {
|
| + size = window_delegate_->GetController()->GetModeSize();
|
| + }
|
| + // 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;
|
| +
|
| + size_ = size;
|
| + return true;
|
| +}
|
| +
|
| +intptr_t GbmSurface::GetNativeWindow() {
|
| + DCHECK(native_surface_);
|
| + return reinterpret_cast<intptr_t>(native_surface_);
|
| +}
|
| +
|
| +bool GbmSurface::ResizeNativeWindow(const gfx::Size& viewport_size) {
|
| + if (size_ == viewport_size)
|
| + return true;
|
| +
|
| + return false;
|
| +}
|
| +
|
| +bool GbmSurface::OnSwapBuffers() {
|
| + return OnSwapBuffersAsync(base::Bind(&DoNothing));
|
| +}
|
| +
|
| +bool GbmSurface::OnSwapBuffersAsync(const SwapCompletionCallback& callback) {
|
| + DCHECK(native_surface_);
|
| +
|
| + gbm_bo* pending_buffer = gbm_surface_lock_front_buffer(native_surface_);
|
| + scoped_refptr<GbmSurfaceBuffer> primary =
|
| + GbmSurfaceBuffer::GetBuffer(pending_buffer);
|
| + if (!primary.get()) {
|
| + primary = GbmSurfaceBuffer::CreateBuffer(gbm_, pending_buffer);
|
| + if (!primary.get()) {
|
| + LOG(ERROR) << "Failed to associate the buffer with the controller";
|
| + callback.Run(gfx::SwapResult::SWAP_FAILED);
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + // The primary buffer is a special case.
|
| + window_delegate_->QueueOverlayPlane(OverlayPlane(primary));
|
| +
|
| + if (!GbmSurfaceless::OnSwapBuffersAsync(
|
| + base::Bind(&GbmSurface::OnSwapBuffersCallback,
|
| + weak_factory_.GetWeakPtr(), callback, pending_buffer))) {
|
| + callback.Run(gfx::SwapResult::SWAP_FAILED);
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +void GbmSurface::OnSwapBuffersCallback(const SwapCompletionCallback& callback,
|
| + gbm_bo* pending_buffer,
|
| + gfx::SwapResult result) {
|
| + // If there was a frontbuffer, it is no longer active. Release it back to GBM.
|
| + if (current_buffer_)
|
| + gbm_surface_release_buffer(native_surface_, current_buffer_);
|
| +
|
| + current_buffer_ = pending_buffer;
|
| + callback.Run(result);
|
| +}
|
| +
|
| +} // namespace ui
|
|
|