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

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

Issue 225023009: Add Intel DRM backed GpuMemoryBuffer implementation. Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 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..5be371be7486905c744b0f1b751ddde23566f7d4
--- /dev/null
+++ b/content/common/gpu/client/gpu_memory_buffer_impl_intel_drm.cc
@@ -0,0 +1,291 @@
+// 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/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;
+
+int WriteEnable(gfx::GpuMemoryBuffer::AccessMode mode) {
+ switch (mode) {
+ case gfx::GpuMemoryBuffer::READ_ONLY:
+ return 0;
+ case gfx::GpuMemoryBuffer::WRITE_ONLY:
+ case gfx::GpuMemoryBuffer::READ_WRITE:
+ return 1;
+ }
+
+ NOTREACHED();
+ return 0;
+}
+
+void ExportBufferObject(drm_intel_bo* buffer_object,
+ base::SharedMemoryHandle* handle) {
+ int prime_fd = -1;
+ drm_intel_bo_gem_export_to_prime(buffer_object, &prime_fd);
+ *handle = base::FileDescriptor(prime_fd, true);
+}
+
+uint64 BufferObjectPitch(gfx::Size size, unsigned internalformat) {
+ return static_cast<uint64>(size.width()) *
+ GpuMemoryBufferImpl::BytesPerPixel(internalformat);
+}
+
+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.";
+ }
+ ~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_pitch = BufferObjectPitch(size, internalformat);
+ if (expected_pitch > std::numeric_limits<uint32>::max())
+ return NULL;
+
+ uint32_t tiling_mode = I915_TILING_NONE;
+ unsigned long pitch = 0;
+ drm_intel_bo* buffer_object = drm_intel_bo_alloc_tiled(
+ buffer_manager_,
+ "ChromiumGpuMemoryBuffer",
+ size.width(),
+ size.height(),
+ GpuMemoryBufferImpl::BytesPerPixel(internalformat),
+ &tiling_mode,
+ &pitch,
+ 0);
+ if (!buffer_object) {
+ LOG(ERROR) << "drm_intel_bo_alloc_tiled failed.";
+ return NULL;
+ }
+
+ // |pitch| must match what we expect.
+ if (static_cast<uint64>(pitch) != expected_pitch) {
+ LOG(ERROR) << "Unexpected pitch: " << pitch << " vs " << expected_pitch;
+ 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 pitch = BufferObjectPitch(size, internalformat);
+ if (pitch > std::numeric_limits<uint32>::max())
+ return NULL;
+
+ uint64 buffer_size = pitch * size.height();
+ if (buffer_size > std::numeric_limits<int32>::max())
fjhenigman 2014/04/09 16:33:52 should be uint32
reveman 2014/04/09 18:22:22 Fixed by using base::IsValueInRangeForNumericType
+ return NULL;
+
+ return drm_intel_bo_gem_create_from_prime(
+ buffer_manager_, prime_fd, buffer_size);
+ }
+
+ private:
+ base::ThreadChecker thread_checker_;
+ 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;
+
+ ExportBufferObject(buffer_object, handle);
+ drm_intel_bo_unreference(buffer_object);
+ return true;
+}
+
+bool GpuMemoryBufferImplIntelDRM::Initialize(
+ gfx::GpuMemoryBufferHandle handle) {
+ TRACE_EVENT0("gpu", "GpuMemoryBufferImplIntelDRM::Initialize");
+
+ DCHECK(!buffer_object_);
+ buffer_object_ =
+ g_buffer_object_factory.Pointer()->CreateBufferObjectFromPrimeFd(
+ size_, internalformat_, handle.handle.fd);
+ return !!buffer_object_;
+}
+
+bool GpuMemoryBufferImplIntelDRM::InitializeFromBufferObject(
+ drm_intel_bo* buffer_object) {
+ DCHECK(!buffer_object_);
+ buffer_object_ = buffer_object;
+ return true;
+}
+
+void* GpuMemoryBufferImplIntelDRM::Map(AccessMode mode) {
+ TRACE_EVENT0("gpu", "GpuMemoryBufferImplIntelDRM::Map");
+
+ DCHECK(!mapped_);
+ DCHECK(buffer_object_);
+ drm_intel_bo_map(buffer_object_, WriteEnable(mode));
+ mapped_ = true;
+ return buffer_object_->virt;
+}
+
+void GpuMemoryBufferImplIntelDRM::Unmap() {
+ TRACE_EVENT0("gpu", "GpuMemoryBufferImplIntelDRM::Unmap");
+
+ DCHECK(mapped_);
+ drm_intel_bo_unmap(buffer_object_);
+ mapped_ = false;
+}
+
+gfx::GpuMemoryBufferHandle GpuMemoryBufferImplIntelDRM::GetHandle() const {
+ gfx::GpuMemoryBufferHandle handle;
+ handle.type = gfx::INTEL_DRM_BUFFER;
+ DCHECK(buffer_object_);
+ ExportBufferObject(buffer_object_, &handle.handle);
+ return handle;
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698