OLD | NEW |
| (Empty) |
1 // Copyright 2013 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/gfx/ozone/impl/dri_skbitmap.h" | |
6 | |
7 #include <errno.h> | |
8 #include <sys/mman.h> | |
9 #include <sys/types.h> | |
10 #include <xf86drm.h> | |
11 | |
12 #include "base/compiler_specific.h" | |
13 #include "base/logging.h" | |
14 #include "third_party/skia/include/core/SkPixelRef.h" | |
15 | |
16 namespace gfx { | |
17 | |
18 namespace { | |
19 | |
20 void DestroyDumbBuffer(int fd, uint32_t handle) { | |
21 struct drm_mode_destroy_dumb destroy_request; | |
22 destroy_request.handle = handle; | |
23 drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_request); | |
24 } | |
25 | |
26 // Special DRM implementation of a SkPixelRef. The DRM allocator will create a | |
27 // SkPixelRef for the backing pixels. It will then associate the SkPixelRef with | |
28 // the SkBitmap. SkBitmap will access the allocated memory by locking the pixels | |
29 // in the SkPixelRef. | |
30 // At the end of its life the SkPixelRef is responsible for deallocating the | |
31 // pixel memory. | |
32 class DriSkPixelRef : public SkPixelRef { | |
33 public: | |
34 DriSkPixelRef(void* pixels, | |
35 SkColorTable* color_table_, | |
36 size_t size, | |
37 int fd, | |
38 uint32_t handle); | |
39 virtual ~DriSkPixelRef(); | |
40 | |
41 virtual void* onLockPixels(SkColorTable** ct) OVERRIDE; | |
42 virtual void onUnlockPixels() OVERRIDE; | |
43 | |
44 SK_DECLARE_UNFLATTENABLE_OBJECT() | |
45 private: | |
46 // Raw pointer to the pixel memory. | |
47 void* pixels_; | |
48 | |
49 // Optional color table associated with the pixel memory. | |
50 SkColorTable* color_table_; | |
51 | |
52 // Size of the allocated memory. | |
53 size_t size_; | |
54 | |
55 // File descriptor to the graphics card used to allocate/deallocate the | |
56 // memory. | |
57 int fd_; | |
58 | |
59 // Handle for the allocated memory. | |
60 uint32_t handle_; | |
61 | |
62 DISALLOW_COPY_AND_ASSIGN(DriSkPixelRef); | |
63 }; | |
64 | |
65 //////////////////////////////////////////////////////////////////////////////// | |
66 // DriSkPixelRef implementation | |
67 | |
68 DriSkPixelRef::DriSkPixelRef( | |
69 void* pixels, | |
70 SkColorTable* color_table, | |
71 size_t size, | |
72 int fd, | |
73 uint32_t handle) | |
74 : pixels_(pixels), | |
75 color_table_(color_table), | |
76 size_(size), | |
77 fd_(fd), | |
78 handle_(handle) { | |
79 } | |
80 | |
81 DriSkPixelRef::~DriSkPixelRef() { | |
82 munmap(pixels_, size_); | |
83 DestroyDumbBuffer(fd_, handle_); | |
84 } | |
85 | |
86 void* DriSkPixelRef::onLockPixels(SkColorTable** ct) { | |
87 *ct = color_table_; | |
88 return pixels_; | |
89 } | |
90 | |
91 void DriSkPixelRef::onUnlockPixels() { | |
92 } | |
93 | |
94 } // namespace | |
95 | |
96 // Allocates pixel memory for a SkBitmap using DRM dumb buffers. | |
97 class DriAllocator : public SkBitmap::Allocator { | |
98 public: | |
99 DriAllocator(); | |
100 | |
101 virtual bool allocPixelRef(SkBitmap* bitmap, | |
102 SkColorTable* color_table) OVERRIDE; | |
103 | |
104 private: | |
105 bool AllocatePixels(DriSkBitmap* bitmap, SkColorTable* color_table); | |
106 | |
107 DISALLOW_COPY_AND_ASSIGN(DriAllocator); | |
108 }; | |
109 | |
110 //////////////////////////////////////////////////////////////////////////////// | |
111 // DriAllocator implementation | |
112 | |
113 DriAllocator::DriAllocator() { | |
114 } | |
115 | |
116 bool DriAllocator::allocPixelRef(SkBitmap* bitmap, | |
117 SkColorTable* color_table) { | |
118 return AllocatePixels(static_cast<DriSkBitmap*>(bitmap), color_table); | |
119 } | |
120 | |
121 bool DriAllocator::AllocatePixels(DriSkBitmap* bitmap, | |
122 SkColorTable* color_table) { | |
123 struct drm_mode_create_dumb request; | |
124 request.width = bitmap->width(); | |
125 request.height = bitmap->height(); | |
126 request.bpp = bitmap->bytesPerPixel() << 3; | |
127 request.flags = 0; | |
128 | |
129 if (drmIoctl(bitmap->get_fd(), DRM_IOCTL_MODE_CREATE_DUMB, &request) < 0) { | |
130 DLOG(ERROR) << "Cannot create dumb buffer (" << errno << ") " | |
131 << strerror(errno); | |
132 return false; | |
133 } | |
134 | |
135 CHECK(request.size == bitmap->getSize()); | |
136 | |
137 bitmap->set_handle(request.handle); | |
138 | |
139 struct drm_mode_map_dumb map_request; | |
140 map_request.handle = bitmap->get_handle(); | |
141 if (drmIoctl(bitmap->get_fd(), DRM_IOCTL_MODE_MAP_DUMB, &map_request)) { | |
142 DLOG(ERROR) << "Cannot prepare dumb buffer for mapping (" << errno << ") " | |
143 << strerror(errno); | |
144 DestroyDumbBuffer(bitmap->get_fd(), bitmap->get_handle()); | |
145 return false; | |
146 } | |
147 | |
148 void* pixels = mmap(0, | |
149 bitmap->getSize(), | |
150 PROT_READ | PROT_WRITE, | |
151 MAP_SHARED, | |
152 bitmap->get_fd(), | |
153 map_request.offset); | |
154 if (pixels == MAP_FAILED) { | |
155 DLOG(ERROR) << "Cannot mmap dumb buffer (" << errno << ") " | |
156 << strerror(errno); | |
157 DestroyDumbBuffer(bitmap->get_fd(), bitmap->get_handle()); | |
158 return false; | |
159 } | |
160 | |
161 bitmap->setPixelRef(new DriSkPixelRef( | |
162 pixels, | |
163 color_table, | |
164 bitmap->getSize(), | |
165 bitmap->get_fd(), | |
166 bitmap->get_handle()))->unref(); | |
167 bitmap->lockPixels(); | |
168 | |
169 return true; | |
170 } | |
171 | |
172 //////////////////////////////////////////////////////////////////////////////// | |
173 // DriSkBitmap implementation | |
174 | |
175 DriSkBitmap::DriSkBitmap(int fd) | |
176 : fd_(fd), | |
177 handle_(0), | |
178 framebuffer_(0) { | |
179 } | |
180 | |
181 DriSkBitmap::~DriSkBitmap() { | |
182 } | |
183 | |
184 bool DriSkBitmap::Initialize() { | |
185 DriAllocator drm_allocator; | |
186 return allocPixels(&drm_allocator, NULL); | |
187 } | |
188 | |
189 uint8_t DriSkBitmap::GetColorDepth() const { | |
190 switch (config()) { | |
191 case SkBitmap::kNo_Config: | |
192 case SkBitmap::kA1_Config: | |
193 case SkBitmap::kA8_Config: | |
194 return 0; | |
195 case SkBitmap::kIndex8_Config: | |
196 return 8; | |
197 case SkBitmap::kRGB_565_Config: | |
198 return 16; | |
199 case SkBitmap::kARGB_4444_Config: | |
200 return 12; | |
201 case SkBitmap::kARGB_8888_Config: | |
202 return 24; | |
203 default: | |
204 NOTREACHED(); | |
205 return 0; | |
206 } | |
207 } | |
208 | |
209 } // namespace gfx | |
OLD | NEW |