| 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..592c7cbfa477d4a208a8ffed4ac50df418b60728
|
| --- /dev/null
|
| +++ b/ui/ozone/platform/drm/gpu/intel_drm_pixmap.cc
|
| @@ -0,0 +1,266 @@
|
| +// 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 <libdrm/i915_drm.h>
|
| +extern "C" {
|
| +#include <libdrm/intel_bufmgr.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 "base/threading/thread_checker.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) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + 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 {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + return buffer_manager_;
|
| + }
|
| + int device_fd() const {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + return device_fd_.fd;
|
| + }
|
| +
|
| + private:
|
| + base::FileDescriptor device_fd_;
|
| + drm_intel_bufmgr* buffer_manager_;
|
| + base::ThreadChecker thread_checker_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(DrmIntelBufferManager);
|
| +};
|
| +
|
| +int BytesPerPixel(SurfaceFactoryOzone::BufferFormat format) {
|
| + switch (format) {
|
| + case SurfaceFactoryOzone::BGRA_8888:
|
| + case SurfaceFactoryOzone::RGBX_8888:
|
| + return 4;
|
| + default:
|
| + NOTREACHED();
|
| + return 0;
|
| + }
|
| +}
|
| +
|
| +unsigned long StrideInBytes(int width,
|
| + SurfaceFactoryOzone::BufferFormat format) {
|
| + base::CheckedNumeric<unsigned long> s = width;
|
| + switch (format) {
|
| + case SurfaceFactoryOzone::BGRA_8888:
|
| + case SurfaceFactoryOzone::RGBX_8888:
|
| + s *= BytesPerPixel(format);
|
| + DCHECK(s.IsValid());
|
| + return s.ValueOrDie();
|
| + default:
|
| + NOTREACHED();
|
| + return 0;
|
| + }
|
| +}
|
| +
|
| +base::LazyInstance<DrmIntelBufferManager>::Leaky g_buffer_manager =
|
| + LAZY_INSTANCE_INITIALIZER;
|
| +
|
| +} // namespace
|
| +
|
| +// static
|
| +scoped_refptr<IntelDrmPixmap> IntelDrmPixmap::Create(
|
| + base::FileDescriptor device_fd,
|
| + SurfaceFactoryOzone::BufferFormat format,
|
| + const gfx::Size& size) {
|
| + TRACE_EVENT2("drm", "IntelDrmPixmap::Create", "format", format, "size",
|
| + size.ToString());
|
| +
|
| + scoped_refptr<IntelDrmPixmap> pixmap(new IntelDrmPixmap());
|
| + if (!pixmap->Initialize(device_fd, format, size))
|
| + return nullptr;
|
| +
|
| + return pixmap;
|
| +}
|
| +
|
| +// static
|
| +scoped_refptr<IntelDrmPixmap> IntelDrmPixmap::CreateFromHandle(
|
| + base::FileDescriptor device_fd,
|
| + base::FileDescriptor handle,
|
| + SurfaceFactoryOzone::BufferFormat format,
|
| + const gfx::Size& size) {
|
| + TRACE_EVENT2("drm", "IntelDrmPixmap::CreateFromHandle", "format", format,
|
| + "size", size.ToString());
|
| +
|
| + scoped_refptr<IntelDrmPixmap> pixmap(new IntelDrmPixmap());
|
| + if (!pixmap->InitializeFromHandle(device_fd, handle, format, size))
|
| + return nullptr;
|
| +
|
| + return pixmap;
|
| +}
|
| +
|
| +IntelDrmPixmap::IntelDrmPixmap() : buffer_(nullptr), stride_(0) {
|
| +}
|
| +
|
| +bool IntelDrmPixmap::Initialize(base::FileDescriptor device_fd,
|
| + SurfaceFactoryOzone::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);
|
| + }
|
| +
|
| + unsigned long expected_stride = StrideInBytes(size.width(), format);
|
| + 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;
|
| + }
|
| +
|
| + // It's possible that StrideInBytes() doesn't match that of the driver.
|
| + // It's why it sends |stride| to render process.
|
| + if (stride != expected_stride) {
|
| + DLOG(WARNING) << "Unexpected stride: " << stride << " vs "
|
| + << expected_stride;
|
| + }
|
| + 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;
|
| +}
|
| +
|
| +bool IntelDrmPixmap::InitializeFromHandle(
|
| + base::FileDescriptor device_fd,
|
| + base::FileDescriptor handle,
|
| + SurfaceFactoryOzone::BufferFormat format,
|
| + const gfx::Size& size) {
|
| + if (!g_buffer_manager.Pointer()->buffer_manager()) {
|
| + g_buffer_manager.Pointer()->Initialize(device_fd);
|
| + }
|
| +
|
| + stride_ = StrideInBytes(size.width(), format);
|
| + int buffer_size = stride_ * size.height();
|
| + buffer_ = drm_intel_bo_gem_create_from_prime(
|
| + g_buffer_manager.Pointer()->buffer_manager(), handle.fd, buffer_size);
|
| + if (!buffer_) {
|
| + DLOG(ERROR) << "drm_intel_bo_gem_create_from_prime failed.";
|
| + return false;
|
| + }
|
| + DCHECK(handle.auto_close);
|
| + prime_fd_.reset(handle.fd);
|
| + return true;
|
| +}
|
| +
|
| +IntelDrmPixmap::~IntelDrmPixmap() {
|
| + if (buffer_) {
|
| + drm_intel_bo_unreference(buffer_);
|
| + buffer_ = nullptr;
|
| + }
|
| +}
|
| +
|
| +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;
|
| +}
|
| +
|
| +NativePixmap::BufferUsage IntelDrmPixmap::GetBufferUsage() const {
|
| + return MAP;
|
| +}
|
| +
|
| +void* IntelDrmPixmap::Map() {
|
| + TRACE_EVENT0("gpu", "IntelDrmPixmap::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 nullptr;
|
| + }
|
| + DCHECK(buffer_->virt);
|
| + return buffer_->virt;
|
| +}
|
| +
|
| +void IntelDrmPixmap::Unmap() {
|
| + TRACE_EVENT0("gpu", "IntelDrmPixmap::Unmap");
|
| + DCHECK(buffer_);
|
| + int error = drm_intel_bo_unmap(buffer_);
|
| + DCHECK(!error) << error;
|
| +}
|
| +
|
| +} // namespace ui
|
|
|