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

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: fix typos 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/numerics/safe_conversions.h"
30 #include "base/strings/stringprintf.h"
31 #include "base/threading/thread_checker.h"
32 #include "ui/gl/gl_bindings.h"
33
34 #if defined(USE_X11)
35 #include "ui/gfx/x/x11_types.h"
36 #endif
37
38 namespace content {
39 namespace {
40
41 #if defined(USE_X11)
42 static char g_dri2_extension_name[] = DRI2_NAME;
43 static XExtensionInfo* g_dri2_info;
44 static XExtensionHooks g_dri2_extension_hooks = {NULL, // create_gc
45 NULL, // copy_gc
46 NULL, // flush_gc
47 NULL, // free_gc
48 NULL, // create_font
49 NULL, // free_font
50 NULL, // close_display
51 NULL, // wire_to_event
52 NULL, // event_to_wire
53 NULL, // error
54 NULL, // error_string
55 };
56 static XEXT_GENERATE_FIND_DISPLAY(DRI2FindDisplay,
57 g_dri2_info,
58 g_dri2_extension_name,
59 &g_dri2_extension_hooks,
60 0,
61 NULL);
62
63 bool X11DRI2Authenticate(drm_magic_t magic) {
64 Display* dpy = gfx::GetXDisplay();
65 XExtDisplayInfo* info = DRI2FindDisplay(dpy);
66 XextCheckExtension(dpy, info, g_dri2_extension_name, false);
67 LockDisplay(dpy);
68 xDRI2AuthenticateReq* req;
69 GetReq(DRI2Authenticate, req);
70 req->reqType = info->codes->major_opcode;
71 req->dri2ReqType = X_DRI2Authenticate;
72 req->window = DefaultRootWindow(dpy);
73 req->magic = magic;
74 xDRI2AuthenticateReply rep;
75 int status = _XReply(dpy, reinterpret_cast<xReply*>(&rep), 0, xFalse);
76 UnlockDisplay(dpy);
77 SyncHandle();
78 return status && rep.authenticated;
79 }
80 #endif // USE_X11
81
82 const int kDeviceId = 0;
83 const int kBatchSize = 2048;
84
85 int WriteEnable(gfx::GpuMemoryBuffer::AccessMode mode) {
86 switch (mode) {
87 case gfx::GpuMemoryBuffer::READ_ONLY:
88 return 0;
89 case gfx::GpuMemoryBuffer::WRITE_ONLY:
90 case gfx::GpuMemoryBuffer::READ_WRITE:
91 return 1;
92 }
93
94 NOTREACHED();
95 return 0;
96 }
97
98 void ExportBufferObject(drm_intel_bo* buffer_object,
99 base::SharedMemoryHandle* handle) {
100 int prime_fd = -1;
101 drm_intel_bo_gem_export_to_prime(buffer_object, &prime_fd);
102 *handle = base::FileDescriptor(prime_fd, true);
103 }
104
105 uint64 BufferObjectPitch(gfx::Size size, unsigned internalformat) {
106 return static_cast<uint64>(size.width()) *
107 GpuMemoryBufferImpl::BytesPerPixel(internalformat);
108 }
109
110 class BufferObjectFactory {
111 public:
112 BufferObjectFactory() : buffer_manager_(NULL) {
113 std::string dev_name(
114 base::StringPrintf(DRM_DEV_NAME, DRM_DIR_NAME, kDeviceId));
115 base::ScopedFD dri_fd(open(dev_name.c_str(), O_RDWR));
116 if (dri_fd.get() < 0) {
117 LOG(ERROR) << "Failed to open: " << dev_name;
118 return;
119 }
120
121 #if defined(USE_X11)
122 drm_magic_t magic;
123 if (drmGetMagic(dri_fd.get(), &magic))
124 return;
125
126 if (!X11DRI2Authenticate(magic)) {
127 LOG(ERROR) << "DRI2Authenticate failed.";
128 return;
129 }
130 #endif
131
132 buffer_manager_ = drm_intel_bufmgr_gem_init(dri_fd.get(), kBatchSize);
133 if (!buffer_manager_) {
134 LOG(ERROR) << "drm_intel_bufmgr_gem_init failed.";
135 return;
136 }
137
138 dri_fd_.swap(dri_fd);
139 }
140 ~BufferObjectFactory() {
141 if (buffer_manager_)
142 drm_intel_bufmgr_destroy(buffer_manager_);
143 }
144
145 drm_intel_bo* CreateBufferObject(gfx::Size size, unsigned internalformat) {
146 DCHECK(thread_checker_.CalledOnValidThread());
147
148 if (!buffer_manager_)
149 return NULL;
150
151 uint64 expected_pitch = BufferObjectPitch(size, internalformat);
152 if (!base::IsValueInRangeForNumericType<uint32>(expected_pitch))
153 return NULL;
154
155 uint32_t tiling_mode = I915_TILING_NONE;
156 unsigned long pitch = 0;
157 drm_intel_bo* buffer_object = drm_intel_bo_alloc_tiled(
158 buffer_manager_,
159 "chromium-gpu-memory-buffer",
160 size.width(),
161 size.height(),
162 GpuMemoryBufferImpl::BytesPerPixel(internalformat),
163 &tiling_mode,
164 &pitch,
165 0);
166 if (!buffer_object) {
167 LOG(ERROR) << "drm_intel_bo_alloc_tiled failed.";
168 return NULL;
169 }
170
171 // |pitch| must match what we expect.
172 if (static_cast<uint64>(pitch) != expected_pitch) {
173 LOG(ERROR) << "Unexpected pitch: " << pitch << " vs " << expected_pitch;
174 drm_intel_bo_unreference(buffer_object);
175 return NULL;
176 }
177
178 return buffer_object;
179 }
180
181 drm_intel_bo* CreateBufferObjectFromPrimeFd(gfx::Size size,
182 unsigned internalformat,
183 int prime_fd) {
184 DCHECK(thread_checker_.CalledOnValidThread());
185
186 if (!buffer_manager_)
187 return NULL;
188
189 uint64 pitch = BufferObjectPitch(size, internalformat);
190 if (!base::IsValueInRangeForNumericType<uint32>(pitch))
191 return NULL;
192
193 uint64 buffer_size = pitch * size.height();
194 if (!base::IsValueInRangeForNumericType<int>(buffer_size))
195 return NULL;
196
197 return drm_intel_bo_gem_create_from_prime(
198 buffer_manager_, prime_fd, buffer_size);
199 }
200
201 private:
202 base::ThreadChecker thread_checker_;
203 base::ScopedFD dri_fd_;
204 drm_intel_bufmgr* buffer_manager_;
205 };
206 base::LazyInstance<BufferObjectFactory>::Leaky g_buffer_object_factory =
207 LAZY_INSTANCE_INITIALIZER;
208
209 } // namespace
210
211 GpuMemoryBufferImplIntelDRM::GpuMemoryBufferImplIntelDRM(
212 gfx::Size size,
213 unsigned internalformat)
214 : GpuMemoryBufferImpl(size, internalformat), buffer_object_(NULL) {}
215
216 GpuMemoryBufferImplIntelDRM::~GpuMemoryBufferImplIntelDRM() {
217 if (buffer_object_)
218 drm_intel_bo_unreference(buffer_object_);
219 }
220
221 // static
222 bool GpuMemoryBufferImplIntelDRM::IsFormatSupported(unsigned internalformat) {
223 switch (internalformat) {
224 case GL_BGRA8_EXT:
225 return true;
226 default:
227 return false;
228 }
229 }
230
231 // static
232 drm_intel_bo* GpuMemoryBufferImplIntelDRM::CreateBufferObject(
233 gfx::Size size,
234 unsigned internalformat) {
235 return g_buffer_object_factory.Pointer()->CreateBufferObject(size,
236 internalformat);
237 }
238
239 // static
240 bool GpuMemoryBufferImplIntelDRM::AllocateBufferObject(
241 gfx::Size size,
242 unsigned internalformat,
243 base::SharedMemoryHandle* handle) {
244 drm_intel_bo* buffer_object = CreateBufferObject(size, internalformat);
245 if (!buffer_object)
246 return false;
247
248 ExportBufferObject(buffer_object, handle);
249 drm_intel_bo_unreference(buffer_object);
250 return true;
251 }
252
253 bool GpuMemoryBufferImplIntelDRM::Initialize(
254 gfx::GpuMemoryBufferHandle handle) {
255 TRACE_EVENT0("gpu", "GpuMemoryBufferImplIntelDRM::Initialize");
256
257 DCHECK(!buffer_object_);
258 buffer_object_ =
259 g_buffer_object_factory.Pointer()->CreateBufferObjectFromPrimeFd(
260 size_, internalformat_, handle.handle.fd);
261 return !!buffer_object_;
262 }
263
264 bool GpuMemoryBufferImplIntelDRM::InitializeFromBufferObject(
265 drm_intel_bo* buffer_object) {
266 DCHECK(!buffer_object_);
267 buffer_object_ = buffer_object;
268 return true;
269 }
270
271 void* GpuMemoryBufferImplIntelDRM::Map(AccessMode mode) {
272 TRACE_EVENT0("gpu", "GpuMemoryBufferImplIntelDRM::Map");
273
274 DCHECK(!mapped_);
275 DCHECK(buffer_object_);
276 drm_intel_bo_map(buffer_object_, WriteEnable(mode));
277 mapped_ = true;
278 return buffer_object_->virt;
279 }
280
281 void GpuMemoryBufferImplIntelDRM::Unmap() {
282 TRACE_EVENT0("gpu", "GpuMemoryBufferImplIntelDRM::Unmap");
283
284 DCHECK(mapped_);
285 drm_intel_bo_unmap(buffer_object_);
286 mapped_ = false;
287 }
288
289 gfx::GpuMemoryBufferHandle GpuMemoryBufferImplIntelDRM::GetHandle() const {
290 gfx::GpuMemoryBufferHandle handle;
291 handle.type = gfx::INTEL_DRM_BUFFER;
292 DCHECK(buffer_object_);
293 ExportBufferObject(buffer_object_, &handle.handle);
fjhenigman 2014/04/11 02:45:28 GetHandle() should cache the result of drm_intel_b
reveman 2014/04/11 05:54:27 Done.
294 return handle;
295 }
296
297 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698