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

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

Issue 211133005: [WIP] Not for review. Zero copy. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 6 years, 6 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
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 bool IsHandleValid(const base::FileDescriptor& handle) {
86 return handle.fd >= 0;
87 }
88
89 // Aligns 'value' by rounding it up to the next multiple of 'alignment'
90 uint64 AlignValue(uint64 value, int alignment) {
91 return value + (alignment - (value % alignment)) % alignment;
92 }
93
94 uint64 BufferObjectStride(gfx::Size size, unsigned internalformat) {
95 uint64 stride = static_cast<uint64>(size.width()) *
96 GpuMemoryBufferImpl::BytesPerPixel(internalformat);
97
98 // Note: Intel DRM API doesn't provide an interface that allows us to compute
99 // or query the stride. This should match the driver when untiled.
100 return AlignValue(stride, 64);
101 }
102
103 class BufferObjectFactory {
104 public:
105 BufferObjectFactory() : buffer_manager_(NULL) {
106 std::string dev_name(
107 base::StringPrintf(DRM_DEV_NAME, DRM_DIR_NAME, kDeviceId));
108 base::ScopedFD dri_fd(open(dev_name.c_str(), O_RDWR));
109 if (dri_fd.get() < 0) {
110 LOG(ERROR) << "Failed to open: " << dev_name;
111 return;
112 }
113
114 #if defined(USE_X11)
115 drm_magic_t magic;
116 if (drmGetMagic(dri_fd.get(), &magic))
117 return;
118
119 if (!X11DRI2Authenticate(magic)) {
120 LOG(ERROR) << "DRI2Authenticate failed.";
121 return;
122 }
123 #endif
124
125 buffer_manager_ = drm_intel_bufmgr_gem_init(dri_fd.get(), kBatchSize);
126 if (!buffer_manager_) {
127 LOG(ERROR) << "drm_intel_bufmgr_gem_init failed.";
128 return;
129 }
130
131 dri_fd_.swap(dri_fd);
132 }
133 ~BufferObjectFactory() {
134 if (buffer_manager_)
135 drm_intel_bufmgr_destroy(buffer_manager_);
136 }
137
138 drm_intel_bo* CreateBufferObject(gfx::Size size, unsigned internalformat) {
139 DCHECK(thread_checker_.CalledOnValidThread());
140
141 if (!buffer_manager_)
142 return NULL;
143
144 uint64 expected_stride = BufferObjectStride(size, internalformat);
145 if (!base::IsValueInRangeForNumericType<uint32>(expected_stride))
146 return NULL;
147
148 uint32_t tiling_mode = I915_TILING_NONE;
149 unsigned long stride = 0;
150 drm_intel_bo* buffer_object = drm_intel_bo_alloc_tiled(
151 buffer_manager_,
152 "chromium-gpu-memory-buffer",
153 size.width(),
154 size.height(),
155 GpuMemoryBufferImpl::BytesPerPixel(internalformat),
156 &tiling_mode,
157 &stride,
158 0);
159 if (!buffer_object) {
160 LOG(ERROR) << "drm_intel_bo_alloc_tiled failed.";
161 return NULL;
162 }
163
164 // This might fail if the stride computed by BufferObjectStride() doesn't
165 // match that of the driver.
166 if (static_cast<uint64>(stride) != expected_stride) {
167 LOG(ERROR) << "Unexpected stride: " << stride << " vs "
168 << expected_stride;
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 stride = BufferObjectStride(size, internalformat);
185 if (!base::IsValueInRangeForNumericType<uint32>(stride))
186 return NULL;
187
188 uint64 buffer_size = stride * size.height();
189 if (!base::IsValueInRangeForNumericType<int>(buffer_size))
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 base::ScopedFD dri_fd_;
199 drm_intel_bufmgr* buffer_manager_;
200 };
201 base::LazyInstance<BufferObjectFactory>::Leaky g_buffer_object_factory =
202 LAZY_INSTANCE_INITIALIZER;
203
204 } // namespace
205
206 GpuMemoryBufferImplIntelDRM::GpuMemoryBufferImplIntelDRM(
207 gfx::Size size,
208 unsigned internalformat)
209 : GpuMemoryBufferImpl(size, internalformat), buffer_object_(NULL) {}
210
211 GpuMemoryBufferImplIntelDRM::~GpuMemoryBufferImplIntelDRM() {
212 if (buffer_object_)
213 drm_intel_bo_unreference(buffer_object_);
214 }
215
216 // static
217 bool GpuMemoryBufferImplIntelDRM::IsFormatSupported(unsigned internalformat) {
218 switch (internalformat) {
219 case GL_BGRA8_EXT:
220 return true;
221 default:
222 return false;
223 }
224 }
225
226 // static
227 drm_intel_bo* GpuMemoryBufferImplIntelDRM::CreateBufferObject(
228 gfx::Size size,
229 unsigned internalformat) {
230 return g_buffer_object_factory.Pointer()->CreateBufferObject(size,
231 internalformat);
232 }
233
234 // static
235 bool GpuMemoryBufferImplIntelDRM::AllocateBufferObject(
236 gfx::Size size,
237 unsigned internalformat,
238 base::SharedMemoryHandle* handle) {
239 drm_intel_bo* buffer_object = CreateBufferObject(size, internalformat);
240 if (!buffer_object)
241 return false;
242
243 int prime_fd = -1;
244 drm_intel_bo_gem_export_to_prime(buffer_object, &prime_fd);
245 drm_intel_bo_unreference(buffer_object);
246 *handle = base::FileDescriptor(prime_fd, true);
247 return true;
248 }
249
250 bool GpuMemoryBufferImplIntelDRM::Initialize(
251 gfx::GpuMemoryBufferHandle handle) {
252 TRACE_EVENT0("gpu", "GpuMemoryBufferImplIntelDRM::Initialize");
253
254 if (!IsHandleValid(handle.handle))
255 return false;
256
257 // Note: Ownership is passed with |handle|. This requires us to close the file
258 // descriptor before returning from this function when initialization fails.
259 base::ScopedFD prime_fd(handle.handle.fd);
260
261 DCHECK(!buffer_object_);
262 buffer_object_ =
263 g_buffer_object_factory.Pointer()->CreateBufferObjectFromPrimeFd(
264 size_, internalformat_, prime_fd.get());
265 if (!buffer_object_)
266 return false;
267
268 prime_fd_.swap(prime_fd);
269 return true;
270 }
271
272 bool GpuMemoryBufferImplIntelDRM::InitializeFromBufferObject(
273 drm_intel_bo* buffer_object) {
274 DCHECK(!buffer_object_);
275 buffer_object_ = buffer_object;
276
277 int prime_fd = -1;
278 drm_intel_bo_gem_export_to_prime(buffer_object_, &prime_fd);
279 prime_fd_.reset(prime_fd);
280 return true;
281 }
282
283 void* GpuMemoryBufferImplIntelDRM::Map() {
284 TRACE_EVENT0("gpu", "GpuMemoryBufferImplIntelDRM::Map");
285
286 DCHECK(!mapped_);
287 DCHECK(buffer_object_);
288 drm_intel_bo_map(buffer_object_, 1);
289 mapped_ = true;
290 return buffer_object_->virt;
291 }
292
293 void GpuMemoryBufferImplIntelDRM::Unmap() {
294 TRACE_EVENT0("gpu", "GpuMemoryBufferImplIntelDRM::Unmap");
295
296 DCHECK(mapped_);
297 drm_intel_bo_unmap(buffer_object_);
298 mapped_ = false;
299 }
300
301 uint32 GpuMemoryBufferImplIntelDRM::GetStride() const {
302 return BufferObjectStride(size_, internalformat_);
303 }
304
305 gfx::GpuMemoryBufferHandle GpuMemoryBufferImplIntelDRM::GetHandle() const {
306 gfx::GpuMemoryBufferHandle handle;
307 handle.type = gfx::INTEL_DRM_BUFFER;
308 handle.handle = base::FileDescriptor(prime_fd_.get(), true);
309 return handle;
310 }
311
312 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698