Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1124)

Unified Diff: content/common/gpu/client/gpu_memory_buffer_impl_intel_drm.cc

Issue 211133005: [WIP] Not for review. Zero copy. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/common/gpu/client/gpu_memory_buffer_impl_intel_drm.cc
diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_intel_drm.cc b/content/common/gpu/client/gpu_memory_buffer_impl_intel_drm.cc
new file mode 100644
index 0000000000000000000000000000000000000000..97dfa2021de3f32ceb2235ab72ee6043939a47f1
--- /dev/null
+++ b/content/common/gpu/client/gpu_memory_buffer_impl_intel_drm.cc
@@ -0,0 +1,312 @@
+// 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 "content/common/gpu/client/gpu_memory_buffer_impl_intel_drm.h"
+
+extern "C" {
+#include <fcntl.h>
+#include <libdrm/i915_drm.h>
+#include <libdrm/intel_bufmgr.h>
+#include <xf86drm.h>
+#if defined(USE_X11)
+#include <X11/Xlib.h>
+#include <X11/Xlibint.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/extutil.h>
+#include <X11/extensions/dri2proto.h>
+// X11/Xlibint.h define min/max macros which will conflict with std::min/max
+// unless we undefine them here.
+#undef min
+#undef max
+#endif
+}
+
+#include "base/debug/trace_event.h"
+#include "base/files/scoped_file.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/threading/thread_checker.h"
+#include "ui/gl/gl_bindings.h"
+
+#if defined(USE_X11)
+#include "ui/gfx/x/x11_types.h"
+#endif
+
+namespace content {
+namespace {
+
+#if defined(USE_X11)
+static char g_dri2_extension_name[] = DRI2_NAME;
+static XExtensionInfo* g_dri2_info;
+static XExtensionHooks g_dri2_extension_hooks = {NULL, // create_gc
+ NULL, // copy_gc
+ NULL, // flush_gc
+ NULL, // free_gc
+ NULL, // create_font
+ NULL, // free_font
+ NULL, // close_display
+ NULL, // wire_to_event
+ NULL, // event_to_wire
+ NULL, // error
+ NULL, // error_string
+};
+static XEXT_GENERATE_FIND_DISPLAY(DRI2FindDisplay,
+ g_dri2_info,
+ g_dri2_extension_name,
+ &g_dri2_extension_hooks,
+ 0,
+ NULL);
+
+bool X11DRI2Authenticate(drm_magic_t magic) {
+ Display* dpy = gfx::GetXDisplay();
+ XExtDisplayInfo* info = DRI2FindDisplay(dpy);
+ XextCheckExtension(dpy, info, g_dri2_extension_name, false);
+ LockDisplay(dpy);
+ xDRI2AuthenticateReq* req;
+ GetReq(DRI2Authenticate, req);
+ req->reqType = info->codes->major_opcode;
+ req->dri2ReqType = X_DRI2Authenticate;
+ req->window = DefaultRootWindow(dpy);
+ req->magic = magic;
+ xDRI2AuthenticateReply rep;
+ int status = _XReply(dpy, reinterpret_cast<xReply*>(&rep), 0, xFalse);
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return status && rep.authenticated;
+}
+#endif // USE_X11
+
+const int kDeviceId = 0;
+const int kBatchSize = 2048;
+
+bool IsHandleValid(const base::FileDescriptor& handle) {
+ return handle.fd >= 0;
+}
+
+// Aligns 'value' by rounding it up to the next multiple of 'alignment'
+uint64 AlignValue(uint64 value, int alignment) {
+ return value + (alignment - (value % alignment)) % alignment;
+}
+
+uint64 BufferObjectStride(gfx::Size size, unsigned internalformat) {
+ uint64 stride = static_cast<uint64>(size.width()) *
+ GpuMemoryBufferImpl::BytesPerPixel(internalformat);
+
+ // Note: Intel DRM API doesn't provide an interface that allows us to compute
+ // or query the stride. This should match the driver when untiled.
+ return AlignValue(stride, 64);
+}
+
+class BufferObjectFactory {
+ public:
+ BufferObjectFactory() : buffer_manager_(NULL) {
+ std::string dev_name(
+ base::StringPrintf(DRM_DEV_NAME, DRM_DIR_NAME, kDeviceId));
+ base::ScopedFD dri_fd(open(dev_name.c_str(), O_RDWR));
+ if (dri_fd.get() < 0) {
+ LOG(ERROR) << "Failed to open: " << dev_name;
+ return;
+ }
+
+#if defined(USE_X11)
+ drm_magic_t magic;
+ if (drmGetMagic(dri_fd.get(), &magic))
+ return;
+
+ if (!X11DRI2Authenticate(magic)) {
+ LOG(ERROR) << "DRI2Authenticate failed.";
+ return;
+ }
+#endif
+
+ buffer_manager_ = drm_intel_bufmgr_gem_init(dri_fd.get(), kBatchSize);
+ if (!buffer_manager_) {
+ LOG(ERROR) << "drm_intel_bufmgr_gem_init failed.";
+ return;
+ }
+
+ dri_fd_.swap(dri_fd);
+ }
+ ~BufferObjectFactory() {
+ if (buffer_manager_)
+ drm_intel_bufmgr_destroy(buffer_manager_);
+ }
+
+ drm_intel_bo* CreateBufferObject(gfx::Size size, unsigned internalformat) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (!buffer_manager_)
+ return NULL;
+
+ uint64 expected_stride = BufferObjectStride(size, internalformat);
+ if (!base::IsValueInRangeForNumericType<uint32>(expected_stride))
+ return NULL;
+
+ uint32_t tiling_mode = I915_TILING_NONE;
+ unsigned long stride = 0;
+ drm_intel_bo* buffer_object = drm_intel_bo_alloc_tiled(
+ buffer_manager_,
+ "chromium-gpu-memory-buffer",
+ size.width(),
+ size.height(),
+ GpuMemoryBufferImpl::BytesPerPixel(internalformat),
+ &tiling_mode,
+ &stride,
+ 0);
+ if (!buffer_object) {
+ LOG(ERROR) << "drm_intel_bo_alloc_tiled failed.";
+ return NULL;
+ }
+
+ // This might fail if the stride computed by BufferObjectStride() doesn't
+ // match that of the driver.
+ if (static_cast<uint64>(stride) != expected_stride) {
+ LOG(ERROR) << "Unexpected stride: " << stride << " vs "
+ << expected_stride;
+ drm_intel_bo_unreference(buffer_object);
+ return NULL;
+ }
+
+ return buffer_object;
+ }
+
+ drm_intel_bo* CreateBufferObjectFromPrimeFd(gfx::Size size,
+ unsigned internalformat,
+ int prime_fd) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (!buffer_manager_)
+ return NULL;
+
+ uint64 stride = BufferObjectStride(size, internalformat);
+ if (!base::IsValueInRangeForNumericType<uint32>(stride))
+ return NULL;
+
+ uint64 buffer_size = stride * size.height();
+ if (!base::IsValueInRangeForNumericType<int>(buffer_size))
+ return NULL;
+
+ return drm_intel_bo_gem_create_from_prime(
+ buffer_manager_, prime_fd, buffer_size);
+ }
+
+ private:
+ base::ThreadChecker thread_checker_;
+ base::ScopedFD dri_fd_;
+ drm_intel_bufmgr* buffer_manager_;
+};
+base::LazyInstance<BufferObjectFactory>::Leaky g_buffer_object_factory =
+ LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+GpuMemoryBufferImplIntelDRM::GpuMemoryBufferImplIntelDRM(
+ gfx::Size size,
+ unsigned internalformat)
+ : GpuMemoryBufferImpl(size, internalformat), buffer_object_(NULL) {}
+
+GpuMemoryBufferImplIntelDRM::~GpuMemoryBufferImplIntelDRM() {
+ if (buffer_object_)
+ drm_intel_bo_unreference(buffer_object_);
+}
+
+// static
+bool GpuMemoryBufferImplIntelDRM::IsFormatSupported(unsigned internalformat) {
+ switch (internalformat) {
+ case GL_BGRA8_EXT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// static
+drm_intel_bo* GpuMemoryBufferImplIntelDRM::CreateBufferObject(
+ gfx::Size size,
+ unsigned internalformat) {
+ return g_buffer_object_factory.Pointer()->CreateBufferObject(size,
+ internalformat);
+}
+
+// static
+bool GpuMemoryBufferImplIntelDRM::AllocateBufferObject(
+ gfx::Size size,
+ unsigned internalformat,
+ base::SharedMemoryHandle* handle) {
+ drm_intel_bo* buffer_object = CreateBufferObject(size, internalformat);
+ if (!buffer_object)
+ return false;
+
+ int prime_fd = -1;
+ drm_intel_bo_gem_export_to_prime(buffer_object, &prime_fd);
+ drm_intel_bo_unreference(buffer_object);
+ *handle = base::FileDescriptor(prime_fd, true);
+ return true;
+}
+
+bool GpuMemoryBufferImplIntelDRM::Initialize(
+ gfx::GpuMemoryBufferHandle handle) {
+ TRACE_EVENT0("gpu", "GpuMemoryBufferImplIntelDRM::Initialize");
+
+ if (!IsHandleValid(handle.handle))
+ return false;
+
+ // Note: Ownership is passed with |handle|. This requires us to close the file
+ // descriptor before returning from this function when initialization fails.
+ base::ScopedFD prime_fd(handle.handle.fd);
+
+ DCHECK(!buffer_object_);
+ buffer_object_ =
+ g_buffer_object_factory.Pointer()->CreateBufferObjectFromPrimeFd(
+ size_, internalformat_, prime_fd.get());
+ if (!buffer_object_)
+ return false;
+
+ prime_fd_.swap(prime_fd);
+ return true;
+}
+
+bool GpuMemoryBufferImplIntelDRM::InitializeFromBufferObject(
+ drm_intel_bo* buffer_object) {
+ DCHECK(!buffer_object_);
+ buffer_object_ = buffer_object;
+
+ int prime_fd = -1;
+ drm_intel_bo_gem_export_to_prime(buffer_object_, &prime_fd);
+ prime_fd_.reset(prime_fd);
+ return true;
+}
+
+void* GpuMemoryBufferImplIntelDRM::Map() {
+ TRACE_EVENT0("gpu", "GpuMemoryBufferImplIntelDRM::Map");
+
+ DCHECK(!mapped_);
+ DCHECK(buffer_object_);
+ drm_intel_bo_map(buffer_object_, 1);
+ mapped_ = true;
+ return buffer_object_->virt;
+}
+
+void GpuMemoryBufferImplIntelDRM::Unmap() {
+ TRACE_EVENT0("gpu", "GpuMemoryBufferImplIntelDRM::Unmap");
+
+ DCHECK(mapped_);
+ drm_intel_bo_unmap(buffer_object_);
+ mapped_ = false;
+}
+
+uint32 GpuMemoryBufferImplIntelDRM::GetStride() const {
+ return BufferObjectStride(size_, internalformat_);
+}
+
+gfx::GpuMemoryBufferHandle GpuMemoryBufferImplIntelDRM::GetHandle() const {
+ gfx::GpuMemoryBufferHandle handle;
+ handle.type = gfx::INTEL_DRM_BUFFER;
+ handle.handle = base::FileDescriptor(prime_fd_.get(), true);
+ return handle;
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698