Chromium Code Reviews| Index: ui/ozone/platform/drm/gpu/gbm_map_pixmap_intel.cc |
| diff --git a/ui/ozone/platform/drm/gpu/gbm_map_pixmap_intel.cc b/ui/ozone/platform/drm/gpu/gbm_map_pixmap_intel.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..3166e7dc03c1c96c3a819c4b5f6cbb112c96a625 |
| --- /dev/null |
| +++ b/ui/ozone/platform/drm/gpu/gbm_map_pixmap_intel.cc |
| @@ -0,0 +1,168 @@ |
| +// 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/gbm_map_pixmap_intel.h" |
| + |
| +#include <libdrm/i915_drm.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 "ui/ozone/public/platform/drm_intel_buffer_manager.h" |
| + |
| +namespace ui { |
| + |
| +namespace { |
| + |
| +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; |
| + } |
| +} |
| + |
| +bool ShareToRenderProcess(int prime_fd, base::FileDescriptor* new_handle) { |
| + const int new_fd = dup(prime_fd); |
| + if (new_fd < 0) { |
| + DPLOG(ERROR) << "dup() failed."; |
| + return false; |
| + } |
| + |
| + *new_handle = base::FileDescriptor(new_fd, true); |
| + return true; |
| +} |
| + |
| +base::LazyInstance<DrmIntelBufferManager>::Leaky g_buffer_manager = |
| + LAZY_INSTANCE_INITIALIZER; |
| + |
| +} // namespace |
| + |
| +// static |
| +scoped_refptr<GbmMapPixmapIntel> GbmMapPixmapIntel::CreatePixmap( |
| + const scoped_refptr<GbmDevice>& gbm, |
| + SurfaceFactoryOzone::BufferFormat format, |
| + const gfx::Size& size, |
| + gfx::GpuMemoryBufferHandle* handle) { |
| + TRACE_EVENT2("drm", "GbmMapPixmapIntel::CreatePixmap", "device", |
| + gbm->device_path().value(), "size", size.ToString()); |
| + |
| + scoped_refptr<GbmMapPixmapIntel> pixmap(new GbmMapPixmapIntel()); |
| + if (!pixmap->Initialize(gbm, format, size, handle)) |
| + return nullptr; |
| + |
| + return pixmap; |
| +} |
| + |
| +GbmMapPixmapIntel::GbmMapPixmapIntel() : buffer_(nullptr), stride_(0) { |
| +} |
| + |
| +bool GbmMapPixmapIntel::Initialize(const scoped_refptr<GbmDevice>& gbm, |
| + SurfaceFactoryOzone::BufferFormat format, |
| + const gfx::Size& size, |
| + gfx::GpuMemoryBufferHandle* handle) { |
| + DCHECK(handle); |
| + if (!g_buffer_manager.Pointer()->buffer_manager()) { |
| + g_buffer_manager.Pointer()->Initialize( |
| + base::FileDescriptor(gbm->get_fd(), false)); |
| + } else { |
| + DCHECK(g_buffer_manager.Pointer()->device_fd() == gbm->get_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; |
| + handle->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); |
| + base::FileDescriptor dup_handle; |
| + if (!ShareToRenderProcess(prime_fd_.get(), &dup_handle)) { |
| + DLOG(ERROR) << "Fail to duplicate a drm buffer file descriptor"; |
| + return false; |
| + } |
| + |
| + base::FileDescriptor dup_device_handle; |
| + if (!ShareToRenderProcess(gbm->get_fd(), &dup_device_handle)) { |
| + base::ScopedFD fd(dup_handle.fd); |
| + DLOG(ERROR) << "Fail to duplicate a drm file descriptor"; |
| + return false; |
| + } |
| + |
| + handle->handle = dup_handle; |
| + // TODO(dshwang): pass |device_handle| only one time to each render process. |
| + handle->device_handle = dup_device_handle; |
| + return true; |
| +} |
| + |
| +GbmMapPixmapIntel::~GbmMapPixmapIntel() { |
| + if (buffer_) { |
| + // TODO(dshwang): It can fix glitch and crash bugs for Ozone GBM |
| + // This is called after bound texture and bound EGLImage are deleted, |
| + // but causes GPU Process crash in mesa with this log |
| + // "drm intel crash: intel_do_flush_locked failed: Invalid argument" |
| + // After drm_intel_bo_unreference() is called, sometime later, mesa causes |
| + // crash, but gdb cannot catch stack trace. I guess crash happens in |
| + // mesa internal thread. |
| + // Surprisingly, glFinish in ResourceProvider::DeleteResourceInternal() |
| + // fixes this issue also. see ResourceProvider |
| + // drm_intel_bo_unreference(buffer_); |
|
dshwang
2015/04/09 19:12:26
As comment said, this CL has glitch and crash bugs
|
| + buffer_ = nullptr; |
| + } |
| +} |
| + |
| +void* GbmMapPixmapIntel::GetEGLClientBuffer() { |
| + return nullptr; |
| +} |
| + |
| +int GbmMapPixmapIntel::GetDmaBufFd() { |
| + return prime_fd_.get(); |
| +} |
| + |
| +int GbmMapPixmapIntel::GetDmaBufPitch() { |
| + return stride_; |
| +} |
| + |
| +} // namespace ui |