| Index: ui/ozone/platform/drm/gpu/intel_drm_pixmap.cc
|
| diff --git a/ui/ozone/platform/drm/gpu/intel_drm_pixmap.cc b/ui/ozone/platform/drm/gpu/intel_drm_pixmap.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..2923990b084de875d62ce6e76afeba93e963c61d
|
| --- /dev/null
|
| +++ b/ui/ozone/platform/drm/gpu/intel_drm_pixmap.cc
|
| @@ -0,0 +1,259 @@
|
| +// Copyright 2015 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/intel_drm_pixmap.h"
|
| +
|
| +#include <fcntl.h>
|
| +#include <libdrm/i915_drm.h>
|
| +extern "C" {
|
| +#include <libdrm/intel_bufmgr.h>
|
| +}
|
| +
|
| +#include "base/posix/eintr_wrapper.h"
|
| +#include "base/lazy_instance.h"
|
| +#include "base/numerics/safe_math.h"
|
| +#include "base/trace_event/trace_event.h"
|
| +#include "ui/ozone/platform/drm/gpu/gbm_device.h"
|
| +
|
| +#include "base/file_descriptor_posix.h"
|
| +#include "base/memory/scoped_ptr.h"
|
| +#include "ui/ozone/ozone_export.h"
|
| +
|
| +namespace ui {
|
| +
|
| +namespace {
|
| +
|
| +class DrmIntelBufferManager {
|
| + public:
|
| + DrmIntelBufferManager() : buffer_manager_(nullptr) {}
|
| + ~DrmIntelBufferManager() {
|
| + if (buffer_manager_)
|
| + drm_intel_bufmgr_destroy(buffer_manager_);
|
| + if (device_fd_.auto_close)
|
| + base::ScopedFD closing_fd(device_fd_.fd);
|
| + }
|
| +
|
| + bool Initialize(const base::FileDescriptor& device_fd) {
|
| + if (buffer_manager_)
|
| + return true;
|
| +
|
| + device_fd_ = device_fd;
|
| +
|
| + // TODO(dshwang): drm bufmgr doesn't need an execbuffer, so batch size is 0.
|
| + const int kBatchSize = 16 * 4096;
|
| + buffer_manager_ = drm_intel_bufmgr_gem_init(device_fd_.fd, kBatchSize);
|
| + if (!buffer_manager_) {
|
| + DLOG(ERROR) << "drm_intel_bufmgr_gem_init failed.";
|
| + return false;
|
| + }
|
| + return true;
|
| + }
|
| +
|
| + drm_intel_bufmgr* buffer_manager() const { return buffer_manager_; }
|
| + int device_fd() const { return device_fd_.fd; }
|
| +
|
| + private:
|
| + base::FileDescriptor device_fd_;
|
| + drm_intel_bufmgr* buffer_manager_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(DrmIntelBufferManager);
|
| +};
|
| +
|
| +int BytesPerPixel(gfx::BufferFormat format) {
|
| + switch (format) {
|
| + case gfx::BufferFormat::BGRA_8888:
|
| + case gfx::BufferFormat::RGBX_8888:
|
| + return 4;
|
| + default:
|
| + NOTREACHED();
|
| + return 0;
|
| + }
|
| +}
|
| +
|
| +base::LazyInstance<DrmIntelBufferManager>::Leaky g_buffer_manager =
|
| + LAZY_INSTANCE_INITIALIZER;
|
| +
|
| +} // namespace
|
| +
|
| +// static
|
| +scoped_refptr<IntelDrmPixmap> IntelDrmPixmap::Create(
|
| + const base::FileDescriptor& device_fd,
|
| + gfx::BufferFormat format,
|
| + const gfx::Size& size) {
|
| + TRACE_EVENT1("drm", "IntelDrmPixmap::Create", "size", size.ToString());
|
| +
|
| + scoped_refptr<IntelDrmPixmap> pixmap(new IntelDrmPixmap());
|
| + if (!pixmap->Initialize(device_fd, format, size))
|
| + return nullptr;
|
| +
|
| + return pixmap;
|
| +}
|
| +
|
| +IntelDrmPixmap::IntelDrmPixmap() : buffer_(nullptr), stride_(0) {}
|
| +
|
| +IntelDrmPixmap::~IntelDrmPixmap() {
|
| + if (buffer_) {
|
| + drm_intel_bo_unreference(buffer_);
|
| + buffer_ = nullptr;
|
| + }
|
| +}
|
| +bool IntelDrmPixmap::Initialize(const base::FileDescriptor& device_fd,
|
| + gfx::BufferFormat format,
|
| + const gfx::Size& size) {
|
| + if (!g_buffer_manager.Pointer()->buffer_manager()) {
|
| + g_buffer_manager.Pointer()->Initialize(device_fd);
|
| + } else {
|
| + DCHECK(g_buffer_manager.Pointer()->device_fd() == device_fd.fd);
|
| + }
|
| +
|
| + uint32_t tiling_mode = I915_TILING_NONE;
|
| + unsigned long stride = 0;
|
| + buffer_ = drm_intel_bo_alloc_tiled(
|
| + g_buffer_manager.Pointer()->buffer_manager(),
|
| + "chromium-gpu-memory-buffer", size.width(), size.height(),
|
| + BytesPerPixel(format), &tiling_mode, &stride, 0);
|
| + if (!buffer_) {
|
| + DLOG(ERROR) << "drm_intel_bo_alloc_tiled failed.";
|
| + return false;
|
| + }
|
| + DCHECK(stride);
|
| + stride_ = stride;
|
| +
|
| + int prime_fd = -1;
|
| + drm_intel_bo_gem_export_to_prime(buffer_, &prime_fd);
|
| + if (prime_fd <= 0) {
|
| + DLOG(ERROR) << "Fail to export a drm buffer file descriptor";
|
| + return false;
|
| + }
|
| + prime_fd_.reset(prime_fd);
|
| + return true;
|
| +}
|
| +
|
| +void* IntelDrmPixmap::GetEGLClientBuffer() {
|
| + return nullptr;
|
| +}
|
| +
|
| +int IntelDrmPixmap::GetDmaBufFd() {
|
| + return prime_fd_.get();
|
| +}
|
| +
|
| +int IntelDrmPixmap::GetDmaBufPitch() {
|
| + return stride_;
|
| +}
|
| +
|
| +bool IntelDrmPixmap::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
|
| + int plane_z_order,
|
| + gfx::OverlayTransform plane_transform,
|
| + const gfx::Rect& display_bounds,
|
| + const gfx::RectF& crop_rect) {
|
| + // IntelDrmPixmap is used in Browser and Renderer, so this feature is not
|
| + // needed.
|
| + NOTREACHED();
|
| + return false;
|
| +}
|
| +
|
| +void IntelDrmPixmap::SetScalingCallback(
|
| + const ScalingCallback& scaling_callback) {
|
| + // IntelDrmPixmap is used in Browser and Renderer, so this feature is not
|
| + // needed.
|
| + NOTREACHED();
|
| +}
|
| +
|
| +scoped_refptr<NativePixmap> IntelDrmPixmap::GetScaledPixmap(
|
| + gfx::Size new_size) {
|
| + // IntelDrmPixmap is used in Browser and Renderer, so this feature is not
|
| + // needed.
|
| + NOTREACHED();
|
| + return nullptr;
|
| +}
|
| +
|
| +gfx::NativePixmapHandle IntelDrmPixmap::ExportHandle() {
|
| + gfx::NativePixmapHandle handle;
|
| +
|
| + int dmabuf_fd = HANDLE_EINTR(dup(prime_fd_.get()));
|
| + if (dmabuf_fd < 0) {
|
| + PLOG(ERROR) << "dup";
|
| + return handle;
|
| + }
|
| +
|
| + handle.fd = base::FileDescriptor(base::ScopedFD(dmabuf_fd));
|
| + handle.stride = stride_;
|
| + return handle;
|
| +}
|
| +
|
| +//////////// IntelDrmClientPixmap
|
| +
|
| +// static
|
| +scoped_ptr<IntelDrmClientPixmap> IntelDrmClientPixmap::CreateFromHandle(
|
| + const gfx::NativePixmapHandle& handle,
|
| + const base::FileDescriptor& device_fd,
|
| + gfx::BufferFormat format,
|
| + const gfx::Size& size) {
|
| + TRACE_EVENT1("drm", "IntelDrmClientPixmap::CreateFromHandle", "size",
|
| + size.ToString());
|
| +
|
| + scoped_ptr<IntelDrmClientPixmap> pixmap(new IntelDrmClientPixmap());
|
| + if (!pixmap->InitializeFromHandle(handle, device_fd, format, size))
|
| + return nullptr;
|
| +
|
| + return pixmap;
|
| +}
|
| +
|
| +IntelDrmClientPixmap::IntelDrmClientPixmap() : buffer_(nullptr), stride_(0) {}
|
| +
|
| +IntelDrmClientPixmap::~IntelDrmClientPixmap() {
|
| + if (buffer_) {
|
| + drm_intel_bo_unreference(buffer_);
|
| + buffer_ = nullptr;
|
| + }
|
| +}
|
| +
|
| +bool IntelDrmClientPixmap::InitializeFromHandle(
|
| + const gfx::NativePixmapHandle& handle,
|
| + const base::FileDescriptor& device_fd,
|
| + gfx::BufferFormat format,
|
| + const gfx::Size& size) {
|
| + if (!g_buffer_manager.Pointer()->buffer_manager()) {
|
| + g_buffer_manager.Pointer()->Initialize(device_fd);
|
| + }
|
| +
|
| + stride_ = handle.stride;
|
| + int buffer_size = stride_ * size.height();
|
| + buffer_ = drm_intel_bo_gem_create_from_prime(
|
| + g_buffer_manager.Pointer()->buffer_manager(), handle.fd.fd, buffer_size);
|
| + if (!buffer_) {
|
| + DLOG(ERROR) << "drm_intel_bo_gem_create_from_prime failed.";
|
| + return false;
|
| + }
|
| + DCHECK(handle.fd.auto_close);
|
| + prime_fd_.reset(handle.fd.fd);
|
| + return true;
|
| +}
|
| +
|
| +bool IntelDrmClientPixmap::Map(void** data) {
|
| + TRACE_EVENT0("gpu", "IntelDrmClientPixmap::Map");
|
| + DCHECK(buffer_);
|
| + int write_enable = 1;
|
| + int error = drm_intel_bo_map(buffer_, write_enable);
|
| + if (error) {
|
| + DLOG(ERROR) << "fail to map a drm buffer. error:" << error;
|
| + return false;
|
| + }
|
| + DCHECK(buffer_->virt);
|
| + *data = buffer_->virt;
|
| + return true;
|
| +}
|
| +
|
| +void IntelDrmClientPixmap::Unmap() {
|
| + TRACE_EVENT0("gpu", "IntelDrmClientPixmap::Unmap");
|
| + DCHECK(buffer_);
|
| + int error = drm_intel_bo_unmap(buffer_);
|
| + DCHECK(!error) << error;
|
| +}
|
| +
|
| +void IntelDrmClientPixmap::GetStride(int* stride) const {
|
| + *stride = stride_;
|
| +}
|
| +
|
| +} // namespace ui
|
|
|