1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ui/ozone/platform/drm/gpu/drm_dumb_buffer.h"
6 
7 #include <drm_fourcc.h>
8 #include <xf86drmMode.h>
9 
10 #include "base/logging.h"
11 #include "third_party/skia/include/core/SkSurface.h"
12 #include "ui/ozone/platform/drm/gpu/drm_device.h"
13 
14 namespace ui {
15 
16 namespace {
17 
DestroyDumbBuffer(const scoped_refptr<DrmDevice> & drm_device,uint32_t handle,DrmDumbBuffer::HandleCloser handle_closer)18 bool DestroyDumbBuffer(const scoped_refptr<DrmDevice>& drm_device,
19                        uint32_t handle,
20                        DrmDumbBuffer::HandleCloser handle_closer) {
21   switch (handle_closer) {
22     case DrmDumbBuffer::HandleCloser::DESTROY_DUMB:
23       return drm_device->DestroyDumbBuffer(handle);
24     case DrmDumbBuffer::HandleCloser::GEM_CLOSE:
25       return drm_device->CloseBufferHandle(handle);
26   }
27 }
28 
29 }  // namespace
30 
DrmDumbBuffer(const scoped_refptr<DrmDevice> & drm)31 DrmDumbBuffer::DrmDumbBuffer(const scoped_refptr<DrmDevice>& drm) : drm_(drm) {}
32 
~DrmDumbBuffer()33 DrmDumbBuffer::~DrmDumbBuffer() {
34   if (mmap_base_ && !drm_->UnmapDumbBuffer(mmap_base_, mmap_size_))
35     PLOG(ERROR) << "DrmDumbBuffer: UnmapDumbBuffer: handle " << handle_;
36 
37   if (handle_ && !DestroyDumbBuffer(drm_, handle_, handle_closer_))
38     PLOG(ERROR) << "DrmDumbBuffer: DestroyDumbBuffer: handle " << handle_;
39 }
40 
Initialize(const SkImageInfo & info)41 bool DrmDumbBuffer::Initialize(const SkImageInfo& info) {
42   DCHECK(!handle_);
43 
44   if (!drm_->CreateDumbBuffer(info, &handle_, &stride_)) {
45     PLOG(ERROR) << "DrmDumbBuffer: CreateDumbBuffer: width " << info.width()
46                 << " height " << info.height();
47     return false;
48   }
49 
50   handle_closer_ = HandleCloser::DESTROY_DUMB;
51 
52   return MapDumbBuffer(info);
53 }
54 
InitializeFromFramebuffer(uint32_t framebuffer_id)55 bool DrmDumbBuffer::InitializeFromFramebuffer(uint32_t framebuffer_id) {
56   DCHECK(!handle_);
57 
58   ScopedDrmFramebufferPtr framebuffer(drm_->GetFramebuffer(framebuffer_id));
59   if (!framebuffer)
60     return false;
61 
62   handle_ = framebuffer->handle;
63   stride_ = framebuffer->pitch;
64   SkImageInfo info =
65       SkImageInfo::MakeN32Premul(framebuffer->width, framebuffer->height);
66 
67   handle_closer_ = HandleCloser::GEM_CLOSE;
68 
69   return MapDumbBuffer(info);
70 }
71 
GetCanvas() const72 SkCanvas* DrmDumbBuffer::GetCanvas() const {
73   return surface_->getCanvas();
74 }
75 
GetHandle() const76 uint32_t DrmDumbBuffer::GetHandle() const {
77   return handle_;
78 }
79 
GetSize() const80 gfx::Size DrmDumbBuffer::GetSize() const {
81   return gfx::Size(surface_->width(), surface_->height());
82 }
83 
MapDumbBuffer(const SkImageInfo & info)84 bool DrmDumbBuffer::MapDumbBuffer(const SkImageInfo& info) {
85   mmap_size_ = info.computeByteSize(stride_);
86   if (!drm_->MapDumbBuffer(handle_, mmap_size_, &mmap_base_)) {
87     PLOG(ERROR) << "DrmDumbBuffer: MapDumbBuffer: handle " << handle_;
88     return false;
89   }
90 
91   surface_ = SkSurface::MakeRasterDirect(info, mmap_base_, stride_);
92   if (!surface_) {
93     LOG(ERROR) << "DrmDumbBuffer: Failed to create SkSurface: handle "
94                << handle_;
95     return false;
96   }
97 
98   return true;
99 }
100 
101 }  // namespace ui
102