OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/ozone/platform/dri/dri_buffer.h" | 5 #include "ui/ozone/platform/dri/dri_buffer.h" |
6 | 6 |
7 #include <errno.h> | |
8 #include <sys/mman.h> | |
9 #include <sys/types.h> | |
10 #include <xf86drm.h> | |
11 | |
12 #include "base/logging.h" | 7 #include "base/logging.h" |
13 #include "third_party/skia/include/core/SkCanvas.h" | |
14 #include "ui/ozone/platform/dri/dri_util.h" | |
15 #include "ui/ozone/platform/dri/dri_wrapper.h" | 8 #include "ui/ozone/platform/dri/dri_wrapper.h" |
16 | 9 |
17 namespace ui { | 10 namespace ui { |
18 | 11 |
19 namespace { | 12 namespace { |
20 | 13 |
21 // Modesetting cannot happen from a buffer with transparencies. Return the size | 14 // Modesetting cannot happen from a buffer with transparencies. Return the size |
22 // of a pixel without alpha. | 15 // of a pixel without alpha. |
23 uint8_t GetColorDepth(SkColorType type) { | 16 uint8_t GetColorDepth(SkColorType type) { |
24 switch (type) { | 17 switch (type) { |
25 case kUnknown_SkColorType: | 18 case kUnknown_SkColorType: |
26 case kAlpha_8_SkColorType: | 19 case kAlpha_8_SkColorType: |
27 return 0; | 20 return 0; |
28 case kIndex_8_SkColorType: | 21 case kIndex_8_SkColorType: |
29 return 8; | 22 return 8; |
30 case kRGB_565_SkColorType: | 23 case kRGB_565_SkColorType: |
31 return 16; | 24 return 16; |
32 case kARGB_4444_SkColorType: | 25 case kARGB_4444_SkColorType: |
33 return 12; | 26 return 12; |
34 case kN32_SkColorType: | 27 case kN32_SkColorType: |
35 return 24; | 28 return 24; |
36 default: | 29 default: |
37 NOTREACHED(); | 30 NOTREACHED(); |
38 return 0; | 31 return 0; |
39 } | 32 } |
40 } | 33 } |
41 | 34 |
42 void DestroyDumbBuffer(int fd, uint32_t handle) { | |
43 struct drm_mode_destroy_dumb destroy_request; | |
44 memset(&destroy_request, 0, sizeof(destroy_request)); | |
45 destroy_request.handle = handle; | |
46 drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_request); | |
47 } | |
48 | |
49 bool CreateDumbBuffer(int fd, | |
50 const SkImageInfo& info, | |
51 uint32_t* handle, | |
52 uint32_t* stride) { | |
53 struct drm_mode_create_dumb request; | |
54 memset(&request, 0, sizeof(request)); | |
55 request.width = info.width(); | |
56 request.height = info.height(); | |
57 request.bpp = info.bytesPerPixel() << 3; | |
58 request.flags = 0; | |
59 | |
60 if (drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &request) < 0) { | |
61 VLOG(2) << "Cannot create dumb buffer (" << errno << ") " | |
62 << strerror(errno); | |
63 return false; | |
64 } | |
65 | |
66 // The driver may choose to align the last row as well. We don't care about | |
67 // the last alignment bits since they aren't used for display purposes, so | |
68 // just check that the expected size is <= to what the driver allocated. | |
69 DCHECK_LE(info.getSafeSize(request.pitch), request.size); | |
70 | |
71 *handle = request.handle; | |
72 *stride = request.pitch; | |
73 return true; | |
74 } | |
75 | |
76 } // namespace | 35 } // namespace |
77 | 36 |
78 DriBuffer::DriBuffer(DriWrapper* dri) | 37 DriBuffer::DriBuffer(DriWrapper* dri) |
79 : dri_(dri), handle_(0), framebuffer_(0) {} | 38 : dri_(dri), handle_(0), framebuffer_(0) {} |
80 | 39 |
81 DriBuffer::~DriBuffer() { | 40 DriBuffer::~DriBuffer() { |
82 if (!surface_) | 41 if (!surface_) |
83 return; | 42 return; |
84 | 43 |
85 if (framebuffer_) | 44 if (framebuffer_) |
86 dri_->RemoveFramebuffer(framebuffer_); | 45 dri_->RemoveFramebuffer(framebuffer_); |
87 | 46 |
88 SkImageInfo info; | 47 SkImageInfo info; |
89 void* pixels = const_cast<void*>(surface_->peekPixels(&info, NULL)); | 48 void* pixels = const_cast<void*>(surface_->peekPixels(&info, NULL)); |
90 if (!pixels) | 49 if (!pixels) |
91 return; | 50 return; |
92 | 51 |
93 munmap(pixels, info.getSafeSize(stride_)); | 52 dri_->DestroyDumbBuffer(info, handle_, stride_, pixels); |
94 DestroyDumbBuffer(dri_->get_fd(), handle_); | |
95 } | 53 } |
96 | 54 |
97 bool DriBuffer::Initialize(const SkImageInfo& info) { | 55 bool DriBuffer::Initialize(const SkImageInfo& info) { |
98 void* pixels = NULL; | 56 void* pixels = NULL; |
99 if (!CreateDumbBuffer(dri_->get_fd(), info, &handle_, &stride_)) { | 57 if (!dri_->CreateDumbBuffer(info, &handle_, &stride_, &pixels)) { |
100 VLOG(2) << "Cannot allocate drm dumb buffer"; | 58 VLOG(2) << "Cannot create drm dumb buffer"; |
101 return false; | 59 return false; |
102 } | 60 } |
103 | 61 |
104 if (!MapDumbBuffer(dri_->get_fd(), | |
105 handle_, | |
106 info.getSafeSize(stride_), | |
107 &pixels)) { | |
108 VLOG(2) << "Cannot map drm dumb buffer"; | |
109 DestroyDumbBuffer(dri_->get_fd(), handle_); | |
110 return false; | |
111 } | |
112 | |
113 if (!dri_->AddFramebuffer(info.width(), | 62 if (!dri_->AddFramebuffer(info.width(), |
114 info.height(), | 63 info.height(), |
115 GetColorDepth(info.colorType()), | 64 GetColorDepth(info.colorType()), |
116 info.bytesPerPixel() << 3, | 65 info.bytesPerPixel() << 3, |
117 stride_, | 66 stride_, |
118 handle_, | 67 handle_, |
119 &framebuffer_)) { | 68 &framebuffer_)) { |
120 VLOG(2) << "Failed to register framebuffer: " << strerror(errno); | 69 VLOG(2) << "Failed to register framebuffer: " << strerror(errno); |
121 return false; | 70 return false; |
122 } | 71 } |
123 | 72 |
124 surface_ = skia::AdoptRef(SkSurface::NewRasterDirect(info, pixels, stride_)); | 73 surface_ = skia::AdoptRef(SkSurface::NewRasterDirect(info, pixels, stride_)); |
125 if (!surface_) { | 74 if (!surface_) { |
126 VLOG(2) << "Cannot install Skia pixels for drm buffer"; | 75 VLOG(2) << "Cannot install Skia pixels for drm buffer"; |
127 return false; | 76 return false; |
128 } | 77 } |
129 | 78 |
130 return true; | 79 return true; |
131 } | 80 } |
132 | 81 |
133 } // namespace ui | 82 } // namespace ui |
OLD | NEW |