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