Skip to content

Instantly share code, notes, and snippets.

@tiagovignatti
Created July 27, 2015 16:08
Show Gist options
  • Save tiagovignatti/e9ca94f01a46ebb0e460 to your computer and use it in GitHub Desktop.
Save tiagovignatti/e9ca94f01a46ebb0e460 to your computer and use it in GitHub Desktop.
commit 47aee337cccf43f7018aa2d590c9a471cf6583f0
Author: Tiago Vignatti <[email protected]>
Date: Fri Jul 24 20:50:30 2015 -0300
WIP: Native GpuMemoryBUffer through Prime mmap only
no VGEM, no vendor dependent ioctls. Just dma-buf.
---
.../chromeos/login/chrome_restart_request.cc | 1 +
content/browser/gpu/gpu_process_host.cc | 1 +
.../renderer_host/render_process_host_impl.cc | 1 +
.../drm/common/native_pixmap_manager_gbm.cc | 14 +-
ui/ozone/platform/drm/gbm.gypi | 2 +
ui/ozone/platform/drm/gpu/drm_pixmap.cc | 155 +++++++++++++++++++++
ui/ozone/platform/drm/gpu/drm_pixmap.h | 61 ++++++++
ui/ozone/platform/drm/gpu/gbm_buffer.cc | 4 +-
.../platform/drm/host/drm_display_host_manager.cc | 4 +-
ui/ozone/public/ozone_switches.cc | 3 +
ui/ozone/public/ozone_switches.h | 2 +
11 files changed, 244 insertions(+), 4 deletions(-)
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc
index b9445c6..4ea4e3d 100644
--- a/chrome/browser/chromeos/login/chrome_restart_request.cc
+++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -172,6 +172,7 @@ std::string DeriveCommandLine(const GURL& start_url,
::switches::kOzonePlatform,
::switches::kOzoneUseSurfaceless,
::switches::kOzoneUseIntelDrm,
+ ::switches::kOzoneUseDrm,
#endif
app_list::switches::kDisableSyncAppList,
app_list::switches::kEnableCenteredAppList,
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 3874fc7..9da4335 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -125,6 +125,7 @@ static const char* const kSwitchNames[] = {
switches::kOzonePlatform,
switches::kOzoneUseSurfaceless,
switches::kOzoneUseIntelDrm,
+ switches::kOzoneUseDrm,
#endif
#if defined(USE_X11) && !defined(OS_CHROMEOS)
switches::kX11Display,
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index db412f3..03934f1 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1401,6 +1401,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
#if defined(USE_OZONE)
switches::kOzonePlatform,
switches::kOzoneUseIntelDrm,
+ switches::kOzoneUseDrm,
#endif
#if defined(OS_CHROMEOS)
switches::kDisableVaapiAcceleratedVideoEncode,
diff --git a/ui/ozone/platform/drm/common/native_pixmap_manager_gbm.cc b/ui/ozone/platform/drm/common/native_pixmap_manager_gbm.cc
index 93a7f10..d1b9eaf 100644
--- a/ui/ozone/platform/drm/common/native_pixmap_manager_gbm.cc
+++ b/ui/ozone/platform/drm/common/native_pixmap_manager_gbm.cc
@@ -9,6 +9,7 @@
#include "base/command_line.h"
#include "ui/ozone/platform/drm/gpu/intel_drm_pixmap.h"
+#include "ui/ozone/platform/drm/gpu/drm_pixmap.h"
#include "ui/ozone/public/ozone_switches.h"
namespace ui {
@@ -66,10 +67,21 @@ scoped_refptr<NativePixmap> NativePixmapManagerGbm::CreateFromFileDescriptor(
SurfaceFactoryOzone::BufferUsage usage) {
bool enable_intel_drm = base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kOzoneUseIntelDrm);
+ bool enable_drm = base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kOzoneUseDrm);
+
if (enable_intel_drm && usage == SurfaceFactoryOzone::MAP) {
return IntelDrmPixmap::CreateFromHandle(
base::FileDescriptor(vgem_fd_.get(), false), handle, format, size);
- }
+ } else if (enable_drm && usage == SurfaceFactoryOzone::MAP) {
+ scoped_refptr<DrmPixmap> pixmap(new DrmPixmap(
+ handle, base::FileDescriptor(vgem_fd_.get(), false), size, format,
+ NativePixmapBufferUsageFromSurfaceFactoryOzone(usage)));
+ if (!pixmap->Initialize())
+ return nullptr;
+
+ return pixmap;
+ }
scoped_refptr<VgemPixmap> pixmap(new VgemPixmap(
handle, base::FileDescriptor(vgem_fd_.get(), false), size, format,
diff --git a/ui/ozone/platform/drm/gbm.gypi b/ui/ozone/platform/drm/gbm.gypi
index a5933ee..19a2723 100644
--- a/ui/ozone/platform/drm/gbm.gypi
+++ b/ui/ozone/platform/drm/gbm.gypi
@@ -48,6 +48,8 @@
'gpu/gbm_surface_factory.h',
'gpu/gbm_surfaceless.cc',
'gpu/gbm_surfaceless.h',
+ 'gpu/drm_pixmap.cc',
+ 'gpu/drm_pixmap.h',
'gpu/intel_drm_pixmap.cc',
'gpu/intel_drm_pixmap.h',
'gpu/vgem_pixmap.cc',
diff --git a/ui/ozone/platform/drm/gpu/drm_pixmap.cc b/ui/ozone/platform/drm/gpu/drm_pixmap.cc
new file mode 100644
index 0000000..3344c9b
--- /dev/null
+++ b/ui/ozone/platform/drm/gpu/drm_pixmap.cc
@@ -0,0 +1,155 @@
+// 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/drm_pixmap.h"
+
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <xf86drm.h>
+
+#include "base/trace_event/trace_event.h"
+#include "ui/ozone/public/surface_factory_ozone.h"
+
+namespace ui {
+
+namespace {
+
+size_t StrideInBytes(size_t width, SurfaceFactoryOzone::BufferFormat format) {
+ switch (format) {
+ case SurfaceFactoryOzone::BGRA_8888:
+ case SurfaceFactoryOzone::RGBX_8888:
+ return width * 4;
+ case SurfaceFactoryOzone::UNKNOWN:
+ NOTREACHED();
+ }
+ NOTREACHED();
+ return 0;
+}
+
+} // namespace
+
+DrmPixmap::DrmPixmap(base::FileDescriptor handle,
+ base::FileDescriptor bo_handle,
+ gfx::Size size,
+ SurfaceFactoryOzone::BufferFormat format,
+ BufferUsage usage)
+ : bo_handle_(0),
+ fd_(bo_handle),
+ size_(size),
+ format_(format),
+ usage_(usage),
+ stride_(StrideInBytes(size_.width(), format_)),
+ mmap_ptr_(nullptr) {
+ if (usage_ == MAP) {
+ CHECK(fd_.fd > 0);
+ CHECK(handle.fd > 0);
+ dma_buf_.reset(handle.fd);
+ }
+}
+
+bool DrmPixmap::Initialize() {
+ if (usage_ == SCANOUT)
+ return true;
+
+ DCHECK(fd_.fd);
+ int ret = drmPrimeFDToHandle(fd_.fd, dma_buf_.get(), &bo_handle_);
+ if (ret) {
+ LOG(ERROR) << "drmPrimeFDToHandle failed, handle:" << bo_handle_;
+ return false;
+ }
+ return true;
+}
+
+DrmPixmap::~DrmPixmap() {
+ if (bo_handle_) {
+ DCHECK_EQ(usage_, MAP);
+ struct drm_mode_destroy_dumb destroy;
+ memset(&destroy, 0, sizeof(destroy));
+ destroy.handle = bo_handle_;
+ int ret = drmIoctl(fd_.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy);
+ if (!ret)
+ LOG(ERROR) << "fail to free drm buffer. error:" << ret;
+ bo_handle_ = 0;
+ }
+}
+
+void* DrmPixmap::GetEGLClientBuffer() {
+ return nullptr;
+}
+
+int DrmPixmap::GetDmaBufFd() {
+ return dma_buf_.get();
+}
+
+int DrmPixmap::GetDmaBufPitch() {
+ return stride_;
+}
+
+bool DrmPixmap::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
+ int plane_z_order,
+ gfx::OverlayTransform plane_transform,
+ const gfx::Rect& display_bounds,
+ const gfx::RectF& crop_rect) {
+ // DrmPixmap is used in Browser and Renderer, so this feature is not
+ // needed.
+ NOTREACHED();
+ return false;
+}
+
+void DrmPixmap::SetScalingCallback(
+ const ScalingCallback& scaling_callback) {
+ // DrmPixmap is used in Browser and Renderer, so this feature is not
+ // needed.
+ NOTREACHED();
+}
+
+scoped_refptr<NativePixmap> DrmPixmap::GetScaledPixmap(
+ gfx::Size new_size) {
+ // DrmPixmap is used in Browser and Renderer, so this feature is not
+ // needed.
+ NOTREACHED();
+ return nullptr;
+}
+
+NativePixmap::BufferUsage DrmPixmap::GetBufferUsage() const {
+ return MAP;
+}
+
+void* DrmPixmap::Map() {
+ TRACE_EVENT0("gpu", "DrmPixmap::Map");
+ DCHECK(!mmap_ptr_);
+ DCHECK(bo_handle_);
+ DCHECK_EQ(usage_, MAP);
+
+ // TODO(vignatti): the following snip might not be needed.
+ struct drm_mode_map_dumb mmap_arg;
+ memset(&mmap_arg, 0, sizeof(mmap_arg));
+ mmap_arg.handle = bo_handle_;
+
+ int ret = drmIoctl(fd_.fd, DRM_IOCTL_MODE_MAP_DUMB, &mmap_arg);
+ if (ret) {
+ LOG(ERROR) << "fail to map a vgem buffer. error:" << ret;
+ return nullptr;
+ }
+ DCHECK(mmap_arg.offset);
+
+ size_t size = stride_ * size_.height();
+ mmap_ptr_ = mmap(nullptr, size, (PROT_READ | PROT_WRITE), MAP_SHARED,
+ fd_.fd, mmap_arg.offset);
+ DCHECK(mmap_ptr_ != MAP_FAILED);
+ return mmap_ptr_;
+}
+
+void DrmPixmap::Unmap() {
+ TRACE_EVENT0("gpu", "DrmPixmap::Unmap");
+ DCHECK(mmap_ptr_);
+ DCHECK(bo_handle_);
+
+ size_t size = stride_ * size_.height();
+ int ret = munmap(mmap_ptr_, size);
+ DCHECK(!ret);
+ mmap_ptr_ = nullptr;
+}
+
+} // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/drm_pixmap.h b/ui/ozone/platform/drm/gpu/drm_pixmap.h
new file mode 100644
index 0000000..719ba4c
--- /dev/null
+++ b/ui/ozone/platform/drm/gpu/drm_pixmap.h
@@ -0,0 +1,61 @@
+// 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.
+
+#ifndef UI_OZONE_PLATFORM_DRM_GPU_DRM_PIXMAP_H_
+#define UI_OZONE_PLATFORM_DRM_GPU_DRM_PIXMAP_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/ozone/public/native_pixmap.h"
+#include "ui/ozone/public/surface_factory_ozone.h"
+
+typedef struct _drm_bo drm_bo;
+
+namespace ui {
+
+class DrmPixmap : public NativePixmap {
+ public:
+ DrmPixmap(base::FileDescriptor handle,
+ base::FileDescriptor bo_handle,
+ gfx::Size size,
+ SurfaceFactoryOzone::BufferFormat format,
+ BufferUsage usage);
+ bool Initialize();
+
+ // NativePixmap:
+ void* GetEGLClientBuffer() override;
+ int GetDmaBufFd() override;
+ int GetDmaBufPitch() override;
+
+ bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
+ int plane_z_order,
+ gfx::OverlayTransform plane_transform,
+ const gfx::Rect& display_bounds,
+ const gfx::RectF& crop_rect) override;
+ void SetScalingCallback(const ScalingCallback& scaling_callback) override;
+ scoped_refptr<NativePixmap> GetScaledPixmap(gfx::Size new_size) override;
+ BufferUsage GetBufferUsage() const override;
+ void* Map() override;
+ void Unmap() override;
+
+ protected:
+ ~DrmPixmap() override;
+
+ private:
+ uint32_t bo_handle_;
+ base::ScopedFD dma_buf_;
+ base::FileDescriptor fd_;
+ gfx::Size size_;
+ SurfaceFactoryOzone::BufferFormat format_;
+ BufferUsage usage_;
+ size_t stride_;
+ void* mmap_ptr_;
+
+ DISALLOW_COPY_AND_ASSIGN(DrmPixmap);
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_DRM_GPU_DRM_PIXMAP_H_
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.cc b/ui/ozone/platform/drm/gpu/gbm_buffer.cc
index 9f4d63d..e7e83e1 100644
--- a/ui/ozone/platform/drm/gpu/gbm_buffer.cc
+++ b/ui/ozone/platform/drm/gpu/gbm_buffer.cc
@@ -52,10 +52,10 @@ scoped_refptr<GbmBuffer> GbmBuffer::CreateBuffer(
bool scanout) {
TRACE_EVENT2("drm", "GbmBuffer::CreateBuffer", "device",
gbm->device_path().value(), "size", size.ToString());
- unsigned flags = GBM_BO_USE_RENDERING;
+ unsigned flags = 0;
// GBM_BO_USE_SCANOUT is the hint of x-tiling.
if (scanout)
- flags |= GBM_BO_USE_SCANOUT;
+ flags |= GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
gbm_bo* bo = gbm_bo_create(gbm->device(), size.width(), size.height(),
GetGbmFormatFromBufferFormat(format), flags);
if (!bo)
diff --git a/ui/ozone/platform/drm/host/drm_display_host_manager.cc b/ui/ozone/platform/drm/host/drm_display_host_manager.cc
index fff3c59..1e0ca25 100644
--- a/ui/ozone/platform/drm/host/drm_display_host_manager.cc
+++ b/ui/ozone/platform/drm/host/drm_display_host_manager.cc
@@ -169,7 +169,9 @@ base::FileDescriptor DrmDisplayHostManager::DupVgemFd() {
bool enable_intel_drm = base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kOzoneUseIntelDrm);
- if (enable_intel_drm) {
+ bool enable_drm = base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kOzoneUseDrm);
+ if (enable_intel_drm || enable_drm) {
device_fd = primary_drm_device_file_.get();
device_path = &primary_graphics_card_path_;
}
diff --git a/ui/ozone/public/ozone_switches.cc b/ui/ozone/public/ozone_switches.cc
index ab45746..e2a1916 100644
--- a/ui/ozone/public/ozone_switches.cc
+++ b/ui/ozone/public/ozone_switches.cc
@@ -19,6 +19,9 @@ const char kOzoneUseSurfaceless[] = "ozone-use-surfaceless";
// Use Intel DRM for native GPU memory buffers.
const char kOzoneUseIntelDrm[] = "ozone-use-intel-drm";
+// Use DRM for native GPU memory buffers.
+const char kOzoneUseDrm[] = "ozone-use-drm";
+
// Enable support for a single overlay plane.
const char kOzoneTestSingleOverlaySupport[] =
"ozone-test-single-overlay-support";
diff --git a/ui/ozone/public/ozone_switches.h b/ui/ozone/public/ozone_switches.h
index 10e7235..930b17f 100644
--- a/ui/ozone/public/ozone_switches.h
+++ b/ui/ozone/public/ozone_switches.h
@@ -18,6 +18,8 @@ OZONE_EXPORT extern const char kOzoneUseSurfaceless[];
OZONE_EXPORT extern const char kOzoneUseIntelDrm[];
+OZONE_EXPORT extern const char kOzoneUseDrm[];
+
OZONE_EXPORT extern const char kOzoneTestSingleOverlaySupport[];
OZONE_EXPORT extern const char kOzoneInitialDisplayBounds[];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment