Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(323)

Side by Side Diff: content/common/gpu/client/gpu_memory_buffer_impl_intel_drm.cc

Issue 225023009: Add Intel DRM backed GpuMemoryBuffer implementation. Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 "content/common/gpu/client/gpu_memory_buffer_impl_intel_drm.h"
6
7 extern "C" {
8 #include <fcntl.h>
9 #include <libdrm/i915_drm.h>
10 #include <libdrm/intel_bufmgr.h>
11 #include <xf86drm.h>
12 #if defined(USE_X11)
13 #include <X11/Xlib.h>
14 #include <X11/Xlibint.h>
15 #include <X11/extensions/Xext.h>
16 #include <X11/extensions/extutil.h>
17 #include <X11/extensions/dri2proto.h>
18 // X11/Xlibint.h define min/max macros which will conflict with std::min/max
19 // unless we undefine them here.
20 #undef min
21 #undef max
22 #endif
23 }
24
25 #include "base/debug/trace_event.h"
26 #include "base/files/scoped_file.h"
27 #include "base/lazy_instance.h"
28 #include "base/logging.h"
29 #include "base/strings/stringprintf.h"
30 #include "base/threading/thread_checker.h"
31 #include "ui/gl/gl_bindings.h"
32
33 #if defined(USE_X11)
34 #include "ui/gfx/x/x11_types.h"
35 #endif
36
37 namespace content {
38 namespace {
39
40 #if defined(USE_X11)
41 static char g_dri2_extension_name[] = DRI2_NAME;
42 static XExtensionInfo* g_dri2_info;
43 static XExtensionHooks g_dri2_extension_hooks = {NULL, // create_gc
44 NULL, // copy_gc
45 NULL, // flush_gc
46 NULL, // free_gc
47 NULL, // create_font
48 NULL, // free_font
49 NULL, // close_display
50 NULL, // wire_to_event
51 NULL, // event_to_wire
52 NULL, // error
53 NULL, // error_string
54 };
55 static XEXT_GENERATE_FIND_DISPLAY(DRI2FindDisplay,
56 g_dri2_info,
57 g_dri2_extension_name,
58 &g_dri2_extension_hooks,
59 0,
60 NULL);
61
62 bool X11DRI2Authenticate(drm_magic_t magic) {
63 Display* dpy = gfx::GetXDisplay();
64 XExtDisplayInfo* info = DRI2FindDisplay(dpy);
65 XextCheckExtension(dpy, info, g_dri2_extension_name, false);
66 LockDisplay(dpy);
67 xDRI2AuthenticateReq* req;
68 GetReq(DRI2Authenticate, req);
69 req->reqType = info->codes->major_opcode;
70 req->dri2ReqType = X_DRI2Authenticate;
71 req->window = DefaultRootWindow(dpy);
72 req->magic = magic;
73 xDRI2AuthenticateReply rep;
74 int status = _XReply(dpy, reinterpret_cast<xReply*>(&rep), 0, xFalse);
75 UnlockDisplay(dpy);
76 SyncHandle();
77 return status && rep.authenticated;
78 }
79 #endif // USE_X11
80
81 const int kDeviceId = 0;
82 const int kBatchSize = 2048;
83
84 int WriteEnable(gfx::GpuMemoryBuffer::AccessMode mode) {
85 switch (mode) {
86 case gfx::GpuMemoryBuffer::READ_ONLY:
87 return 0;
88 case gfx::GpuMemoryBuffer::WRITE_ONLY:
89 case gfx::GpuMemoryBuffer::READ_WRITE:
90 return 1;
91 }
92
93 NOTREACHED();
94 return 0;
95 }
96
97 void ExportBufferObject(drm_intel_bo* buffer_object,
98 base::SharedMemoryHandle* handle) {
99 int prime_fd = -1;
100 drm_intel_bo_gem_export_to_prime(buffer_object, &prime_fd);
101 *handle = base::FileDescriptor(prime_fd, true);
102 }
103
104 uint64 BufferObjectPitch(gfx::Size size, unsigned internalformat) {
105 return static_cast<uint64>(size.width()) *
106 GpuMemoryBufferImpl::BytesPerPixel(internalformat);
107 }
108
109 class BufferObjectFactory {
110 public:
111 BufferObjectFactory() : buffer_manager_(NULL) {
112 std::string dev_name(
113 base::StringPrintf(DRM_DEV_NAME, DRM_DIR_NAME, kDeviceId));
114 base::ScopedFD dri_fd(open(dev_name.c_str(), O_RDWR));
115 if (dri_fd.get() < 0) {
116 LOG(ERROR) << "Failed to open: " << dev_name;
117 return;
118 }
119
120 #if defined(USE_X11)
121 drm_magic_t magic;
122 if (drmGetMagic(dri_fd.get(), &magic))
123 return;
124
125 if (!X11DRI2Authenticate(magic)) {
126 LOG(ERROR) << "DRI2Authenticate failed.";
127 return;
128 }
129 #endif
130
131 buffer_manager_ = drm_intel_bufmgr_gem_init(dri_fd.get(), kBatchSize);
132 if (!buffer_manager_)
133 LOG(ERROR) << "drm_intel_bufmgr_gem_init failed.";
134 }
135 ~BufferObjectFactory() {
136 if (buffer_manager_)
137 drm_intel_bufmgr_destroy(buffer_manager_);
138 }
139
140 drm_intel_bo* CreateBufferObject(gfx::Size size, unsigned internalformat) {
141 DCHECK(thread_checker_.CalledOnValidThread());
142
143 if (!buffer_manager_)
144 return NULL;
145
146 uint64 expected_pitch = BufferObjectPitch(size, internalformat);
147 if (expected_pitch > std::numeric_limits<uint32>::max())
148 return NULL;
149
150 uint32_t tiling_mode = I915_TILING_NONE;
151 unsigned long pitch = 0;
152 drm_intel_bo* buffer_object = drm_intel_bo_alloc_tiled(
153 buffer_manager_,
154 "ChromiumGpuMemoryBuffer",
155 size.width(),
156 size.height(),
157 GpuMemoryBufferImpl::BytesPerPixel(internalformat),
158 &tiling_mode,
159 &pitch,
160 0);
161 if (!buffer_object) {
162 LOG(ERROR) << "drm_intel_bo_alloc_tiled failed.";
163 return NULL;
164 }
165
166 // |pitch| must match what we expect.
167 if (static_cast<uint64>(pitch) != expected_pitch) {
168 LOG(ERROR) << "Unexpected pitch: " << pitch << " vs " << expected_pitch;
169 drm_intel_bo_unreference(buffer_object);
170 return NULL;
171 }
172
173 return buffer_object;
174 }
175
176 drm_intel_bo* CreateBufferObjectFromPrimeFd(gfx::Size size,
177 unsigned internalformat,
178 int prime_fd) {
179 DCHECK(thread_checker_.CalledOnValidThread());
180
181 if (!buffer_manager_)
182 return NULL;
183
184 uint64 pitch = BufferObjectPitch(size, internalformat);
185 if (pitch > std::numeric_limits<uint32>::max())
186 return NULL;
187
188 uint64 buffer_size = pitch * size.height();
189 if (buffer_size > std::numeric_limits<int32>::max())
fjhenigman 2014/04/09 16:33:52 should be uint32
reveman 2014/04/09 18:22:22 Fixed by using base::IsValueInRangeForNumericType
190 return NULL;
191
192 return drm_intel_bo_gem_create_from_prime(
193 buffer_manager_, prime_fd, buffer_size);
194 }
195
196 private:
197 base::ThreadChecker thread_checker_;
198 drm_intel_bufmgr* buffer_manager_;
199 };
200 base::LazyInstance<BufferObjectFactory>::Leaky g_buffer_object_factory =
201 LAZY_INSTANCE_INITIALIZER;
202
203 } // namespace
204
205 GpuMemoryBufferImplIntelDRM::GpuMemoryBufferImplIntelDRM(
206 gfx::Size size,
207 unsigned internalformat)
208 : GpuMemoryBufferImpl(size, internalformat), buffer_object_(NULL) {}
209
210 GpuMemoryBufferImplIntelDRM::~GpuMemoryBufferImplIntelDRM() {
211 if (buffer_object_)
212 drm_intel_bo_unreference(buffer_object_);
213 }
214
215 // static
216 bool GpuMemoryBufferImplIntelDRM::IsFormatSupported(unsigned internalformat) {
217 switch (internalformat) {
218 case GL_BGRA8_EXT:
219 return true;
220 default:
221 return false;
222 }
223 }
224
225 // static
226 drm_intel_bo* GpuMemoryBufferImplIntelDRM::CreateBufferObject(
227 gfx::Size size,
228 unsigned internalformat) {
229 return g_buffer_object_factory.Pointer()->CreateBufferObject(size,
230 internalformat);
231 }
232
233 // static
234 bool GpuMemoryBufferImplIntelDRM::AllocateBufferObject(
235 gfx::Size size,
236 unsigned internalformat,
237 base::SharedMemoryHandle* handle) {
238 drm_intel_bo* buffer_object = CreateBufferObject(size, internalformat);
239 if (!buffer_object)
240 return false;
241
242 ExportBufferObject(buffer_object, handle);
243 drm_intel_bo_unreference(buffer_object);
244 return true;
245 }
246
247 bool GpuMemoryBufferImplIntelDRM::Initialize(
248 gfx::GpuMemoryBufferHandle handle) {
249 TRACE_EVENT0("gpu", "GpuMemoryBufferImplIntelDRM::Initialize");
250
251 DCHECK(!buffer_object_);
252 buffer_object_ =
253 g_buffer_object_factory.Pointer()->CreateBufferObjectFromPrimeFd(
254 size_, internalformat_, handle.handle.fd);
255 return !!buffer_object_;
256 }
257
258 bool GpuMemoryBufferImplIntelDRM::InitializeFromBufferObject(
259 drm_intel_bo* buffer_object) {
260 DCHECK(!buffer_object_);
261 buffer_object_ = buffer_object;
262 return true;
263 }
264
265 void* GpuMemoryBufferImplIntelDRM::Map(AccessMode mode) {
266 TRACE_EVENT0("gpu", "GpuMemoryBufferImplIntelDRM::Map");
267
268 DCHECK(!mapped_);
269 DCHECK(buffer_object_);
270 drm_intel_bo_map(buffer_object_, WriteEnable(mode));
271 mapped_ = true;
272 return buffer_object_->virt;
273 }
274
275 void GpuMemoryBufferImplIntelDRM::Unmap() {
276 TRACE_EVENT0("gpu", "GpuMemoryBufferImplIntelDRM::Unmap");
277
278 DCHECK(mapped_);
279 drm_intel_bo_unmap(buffer_object_);
280 mapped_ = false;
281 }
282
283 gfx::GpuMemoryBufferHandle GpuMemoryBufferImplIntelDRM::GetHandle() const {
284 gfx::GpuMemoryBufferHandle handle;
285 handle.type = gfx::INTEL_DRM_BUFFER;
286 DCHECK(buffer_object_);
287 ExportBufferObject(buffer_object_, &handle.handle);
288 return handle;
289 }
290
291 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698