blob: 3aa7cf259558072ac71f586615470aa884f1a6ba [file] [log] [blame]
David Herrmannfd6b3692012-09-28 23:44:22 +02001<?xml version='1.0'?> <!--*-nxml-*-->
2<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
3 "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
4
5<!--
6 Written 2012 by David Herrmann <dh.herrmann@googlemail.com>
7 Dedicated to the Public Domain
8-->
9
10<refentry id="drm-memory">
11 <refentryinfo>
12 <title>Direct Rendering Manager</title>
13 <productname>libdrm</productname>
14 <date>September 2012</date>
15 <authorgroup>
16 <author>
17 <contrib>Developer</contrib>
18 <firstname>David</firstname>
19 <surname>Herrmann</surname>
20 <email>dh.herrmann@googlemail.com</email>
21 </author>
22 </authorgroup>
23 </refentryinfo>
24
25 <refmeta>
26 <refentrytitle>drm-memory</refentrytitle>
27 <manvolnum>7</manvolnum>
28 </refmeta>
29
30 <refnamediv>
31 <refname>drm-memory</refname>
32 <refname>drm-mm</refname>
33 <refname>drm-gem</refname>
34 <refname>drm-ttm</refname>
35 <refpurpose>DRM Memory Management</refpurpose>
36 </refnamediv>
37
38 <refsynopsisdiv>
39 <funcsynopsis>
40 <funcsynopsisinfo>#include &lt;xf86drm.h&gt;</funcsynopsisinfo>
41 </funcsynopsis>
42 </refsynopsisdiv>
43
44 <refsect1>
45 <title>Description</title>
46 <para>Many modern high-end GPUs come with their own memory managers. They
47 even include several different caches that need to be synchronized
48 during access. Textures, framebuffers, command buffers and more need
49 to be stored in memory that can be accessed quickly by the GPU.
50 Therefore, memory management on GPUs is highly driver- and
51 hardware-dependent.</para>
52
53 <para>However, there are several frameworks in the kernel that are used by
54 more than one driver. These can be used for trivial mode-setting
55 without requiring driver-dependent code. But for
56 hardware-accelerated rendering you need to read the manual pages for
57 the driver you want to work with.</para>
58
59 <refsect2>
60 <title>Dumb-Buffers</title>
61 <para>Almost all in-kernel DRM hardware drivers support an API called
62 <emphasis>Dumb-Buffers</emphasis>. This API allows to create buffers
63 of arbitrary size that can be used for scanout. These buffers can be
64 memory mapped via
65 <citerefentry><refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum></citerefentry>
66 so you can render into them on the CPU. However, GPU access to these
67 buffers is often not possible. Therefore, they are fine for simple
68 tasks but not suitable for complex compositions and
69 renderings.</para>
70
71 <para>The <constant>DRM_IOCTL_MODE_CREATE_DUMB</constant> ioctl can be
72 used to create a dumb buffer. The kernel will return a 32bit handle
73 that can be used to manage the buffer with the DRM API. You can
74 create framebuffers with
75 <citerefentry><refentrytitle>drmModeAddFB</refentrytitle><manvolnum>3</manvolnum></citerefentry>
76 and use it for mode-setting and scanout. To access the buffer, you
77 first need to retrieve the offset of the buffer. The
78 <constant>DRM_IOCTL_MODE_MAP_DUMB</constant> ioctl requests the DRM
79 subsystem to prepare the buffer for memory-mapping and returns a
80 fake-offset that can be used with
81 <citerefentry><refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum></citerefentry>.</para>
82
83 <para>The <constant>DRM_IOCTL_MODE_CREATE_DUMB</constant> ioctl takes as
84 argument a structure of type
85 <structname>struct drm_mode_create_dumb</structname>:
86
87<programlisting>
88struct drm_mode_create_dumb {
89 __u32 height;
90 __u32 width;
91 __u32 bpp;
92 __u32 flags;
93
94 __u32 handle;
95 __u32 pitch;
96 __u64 size;
97};
98</programlisting>
99
100 The fields <structfield>height</structfield>,
101 <structfield>width</structfield>, <structfield>bpp</structfield> and
102 <structfield>flags</structfield> have to be provided by the caller.
103 The other fields are filled by the kernel with the return values.
104 <structfield>height</structfield> and
105 <structfield>width</structfield> are the dimensions of the
106 rectangular buffer that is created. <structfield>bpp</structfield>
107 is the number of bits-per-pixel and must be a multiple of
108 <literal>8</literal>. You most commonly want to pass
109 <literal>32</literal> here. The <structfield>flags</structfield>
110 field is currently unused and must be zeroed. Different flags to
111 modify the behavior may be added in the future. After calling the
112 ioctl, the <structfield>handle</structfield>,
113 <structfield>pitch</structfield> and <structfield>size</structfield>
114 fields are filled by the kernel. <structfield>handle</structfield>
115 is a 32bit gem handle that identifies the buffer. This is used by
116 several other calls that take a gem-handle or memory-buffer as
117 argument. The <structfield>pitch</structfield> field is the
118 pitch (or stride) of the new buffer. Most drivers use 32bit or 64bit
119 aligned stride-values. The <structfield>size</structfield> field
120 contains the absolute size in bytes of the buffer. This can normally
121 also be computed with
122 <emphasis>(height * pitch + width) * bpp / 4</emphasis>.</para>
123
124 <para>To prepare the buffer for
125 <citerefentry><refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum></citerefentry>
126 you need to use the <constant>DRM_IOCTL_MODE_MAP_DUMB</constant>
127 ioctl. It takes as argument a structure of type
128 <structname>struct drm_mode_map_dumb</structname>:
129
130<programlisting>
131struct drm_mode_map_dumb {
132 __u32 handle;
133 __u32 pad;
134
135 __u64 offset;
136};
137</programlisting>
138
139 You need to put the gem-handle that was previously retrieved via
140 <constant>DRM_IOCTL_MODE_CREATE_DUMB</constant> into the
141 <structfield>handle</structfield> field. The
142 <structfield>pad</structfield> field is unused padding and must be
143 zeroed. After completion, the <structfield>offset</structfield>
144 field will contain an offset that can be used with
145 <citerefentry><refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum></citerefentry>
146 on the DRM file-descriptor.</para>
147
148 <para>If you don't need your dumb-buffer, anymore, you have to destroy it
149 with <constant>DRM_IOCTL_MODE_DESTROY_DUMB</constant>. If you close
150 the DRM file-descriptor, all open dumb-buffers are automatically
151 destroyed. This ioctl takes as argument a structure of type
152 <structname>struct drm_mode_destroy_dumb</structname>:
153
154<programlisting>
155struct drm_mode_destroy_dumb {
156 __u32 handle;
157};
158</programlisting>
159
160 You only need to put your handle into the
161 <structfield>handle</structfield> field. After this call, the handle
162 is invalid and may be reused for new buffers by the dumb-API.</para>
163
164 </refsect2>
165
166 <refsect2>
167 <title>TTM</title>
168 <para><emphasis>TTM</emphasis> stands for
169 <emphasis>Translation Table Manager</emphasis> and is a generic
170 memory-manager provided by the kernel. It does not provide a common
171 user-space API so you need to look at each driver interface if you
172 want to use it. See for instance the radeon manpages for more
173 information on memory-management with radeon and TTM.</para>
174 </refsect2>
175
176 <refsect2>
177 <title>GEM</title>
178 <para><emphasis>GEM</emphasis> stands for
179 <emphasis>Graphics Execution Manager</emphasis> and is a generic DRM
180 memory-management framework in the kernel, that is used by many
181 different drivers. Gem is designed to manage graphics memory,
182 control access to the graphics device execution context and handle
183 essentially NUMA environment unique to modern graphics hardware. Gem
184 allows multiple applications to share graphics device resources
185 without the need to constantly reload the entire graphics card. Data
186 may be shared between multiple applications with gem ensuring that
187 the correct memory synchronization occurs.</para>
188
189 <para>Gem provides simple mechanisms to manage graphics data and control
190 execution flow within the linux DRM subsystem. However, gem is not a
191 complete framework that is fully driver independent. Instead, if
192 provides many functions that are shared between many drivers, but
193 each driver has to implement most of memory-management with
194 driver-dependent ioctls. This manpage tries to describe the
195 semantics (and if it applies, the syntax) that is shared between all
196 drivers that use gem.</para>
197
198 <para>All GEM APIs are defined as
199 <citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
200 on the DRM file descriptor. An application must be authorized via
201 <citerefentry><refentrytitle>drmAuthMagic</refentrytitle><manvolnum>3</manvolnum></citerefentry>
202 to the current DRM-Master to access the GEM subsystem. A driver that
203 does not support gem will return <constant>ENODEV</constant> for all
204 these ioctls. Invalid object handles return
205 <constant>EINVAL</constant> and invalid object names return
206 <constant>ENOENT</constant>.</para>
207
208 <para>Gem provides explicit memory management primitives. System pages are
209 allocated when the object is created, either as the fundamental
210 storage for hardware where system memory is used by the graphics
211 processor directly, or as backing store for graphics-processor
212 resident memory.</para>
213
214 <para>Objects are referenced from user-space using handles. These are, for
215 all intents and purposes, equivalent to file descriptors but avoid
216 the overhead. Newer kernel drivers also support the
217 <citerefentry><refentrytitle>drm-prime</refentrytitle><manvolnum>7</manvolnum></citerefentry>
218 infrastructure which can return real file-descriptor for gem-handles
219 using the linux dma-buf API. Objects may be published with a name so
220 that other applications and processes can access them. The name
221 remains valid as long as the object exists. Gem-objects are
222 reference counted in the kernel. The object is only destroyed when
223 all handles from user-space were closed.</para>
224
225 <para>Gem-buffers cannot be created with a generic API. Each driver
226 provides its own API to create gem-buffers. See for example
227 <constant>DRM_I915_GEM_CREATE</constant>,
228 <constant>DRM_NOUVEAU_GEM_NEW</constant> or
229 <constant>DRM_RADEON_GEM_CREATE</constant>. Each of these ioctls
230 returns a gem-handle that can be passed to different generic ioctls.
231 The <emphasis>libgbm</emphasis> library from the
232 <emphasis>mesa3D</emphasis> distribution tries to provide a
233 driver-independent API to create gbm buffers and retrieve a
234 gbm-handle to them. It allows to create buffers for different
235 use-cases including scanout, rendering, cursors and CPU-access. See
236 the libgbm library for more information or look at the
237 driver-dependent man-pages (for example
238 <citerefentry><refentrytitle>drm-intel</refentrytitle><manvolnum>7</manvolnum></citerefentry>
239 or
240 <citerefentry><refentrytitle>drm-radeon</refentrytitle><manvolnum>7</manvolnum></citerefentry>).</para>
241
242 <para>Gem-buffers can be closed with the
243 <constant>DRM_IOCTL_GEM_CLOSE</constant> ioctl. It takes as argument
244 a structure of type <structname>struct drm_gem_close</structname>:
245
246<programlisting>
247struct drm_gem_close {
248 __u32 handle;
249 __u32 pad;
250};
251</programlisting>
252
253 The <structfield>handle</structfield> field is the gem-handle to be
254 closed. The <structfield>pad</structfield> field is unused padding.
255 It must be zeroed. After this call the gem handle cannot be used by
256 this process anymore and may be reused for new gem objects by the
257 gem API.</para>
258
259 <para>If you want to share gem-objects between different processes, you
260 can create a name for them and pass this name to other processes
261 which can then open this gem-object. Names are currently 32bit
262 integer IDs and have no special protection. That is, if you put a
263 name on your gem-object, every other client that has access to the
264 DRM device and is authenticated via
265 <citerefentry><refentrytitle>drmAuthMagic</refentrytitle><manvolnum>3</manvolnum></citerefentry>
266 to the current DRM-Master, can <emphasis>guess</emphasis> the name
267 and open or access the gem-object. If you want more fine-grained
268 access control, you can use the new
269 <citerefentry><refentrytitle>drm-prime</refentrytitle><manvolnum>7</manvolnum></citerefentry>
270 API to retrieve file-descriptors for gem-handles. To create a name
271 for a gem-handle, you use the
272 <constant>DRM_IOCTL_GEM_FLINK</constant> ioctl. It takes as argument
273 a structure of type <structname>struct drm_gem_flink</structname>:
274
275<programlisting>
276struct drm_gem_flink {
277 __u32 handle;
278 __u32 name;
279};
280</programlisting>
281
282 You have to put your handle into the
283 <structfield>handle</structfield> field. After completion, the
284 kernel has put the new unique name into the
285 <structfield>name</structfield> field. You can now pass this name to
286 other processes which can then import the name with the
287 <constant>DRM_IOCTL_GEM_OPEN</constant> ioctl. It takes as argument
288 a structure of type <structname>struct drm_gem_open</structname>:
289
290<programlisting>
291struct drm_gem_open {
292 __u32 name;
293
294 __u32 handle;
295 __u32 size;
296};
297</programlisting>
298
299 You have to fill in the <structfield>name</structfield> field with
300 the name of the gem-object that you want to open. The kernel will
301 fill in the <structfield>handle</structfield> and
302 <structfield>size</structfield> fields with the new handle and size
303 of the gem-object. You can now access the gem-object via the handle
304 as if you created it with the gem API.</para>
305
306 <para>Besides generic buffer management, the GEM API does not provide any
307 generic access. Each driver implements its own functionality on top
308 of this API. This includes execution-buffers, GTT management,
309 context creation, CPU access, GPU I/O and more. The next
310 higher-level API is <emphasis>OpenGL</emphasis>. So if you want to
311 use more GPU features, you should use the
312 <emphasis>mesa3D</emphasis> library to create OpenGL contexts on DRM
313 devices. This does <emphasis>not</emphasis> require any
314 windowing-system like X11, but can also be done on raw DRM devices.
315 However, this is beyond the scope of this man-page. You may have a
316 look at other mesa3D manpages, including libgbm and libEGL. 2D
317 software-rendering (rendering with the CPU) can be achieved with the
318 dumb-buffer-API in a driver-independent fashion, however, for
319 hardware-accelerated 2D or 3D rendering you must use OpenGL. Any
320 other API that tries to abstract the driver-internals to access
321 GEM-execution-buffers and other GPU internals, would simply reinvent
322 OpenGL so it is not provided. But if you need more detailed
323 information for a specific driver, you may have a look into the
324 driver-manpages, including
325 <citerefentry><refentrytitle>drm-intel</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
326 <citerefentry><refentrytitle>drm-radeon</refentrytitle><manvolnum>7</manvolnum></citerefentry>
327 and
328 <citerefentry><refentrytitle>drm-nouveau</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
329 However, the
330 <citerefentry><refentrytitle>drm-prime</refentrytitle><manvolnum>7</manvolnum></citerefentry>
331 infrastructure and the generic gem API as described here allow
332 display-managers to handle graphics-buffers and render-clients
333 without any deeper knowledge of the GPU that is used. Moreover, it
334 allows to move objects between GPUs and implement complex
335 display-servers that don't do any rendering on their own. See its
336 man-page for more information.</para>
337 </refsect2>
338 </refsect1>
339
340 <refsect1>
341 <title>Examples</title>
342 <para>This section includes examples for basic memory-management
343 tasks.</para>
344
345 <refsect2>
346 <title>Dumb-Buffers</title>
347 <para>This examples shows how to create a dumb-buffer via the generic
348 DRM API. This is driver-independent (as long as the driver
349 supports dumb-buffers) and provides memory-mapped buffers that can
350 be used for scanout. This example creates a full-HD 1920x1080
351 buffer with 32 bits-per-pixel and a color-depth of 24 bits. The
352 buffer is then bound to a framebuffer which can be used for
353 scanout with the KMS API (see
354 <citerefentry><refentrytitle>drm-kms</refentrytitle><manvolnum>7</manvolnum></citerefentry>).</para>
355
356<programlisting>
357struct drm_mode_create_dumb creq;
358struct drm_mode_destroy_dumb dreq;
359struct drm_mode_map_dumb mreq;
360uint32_t fb;
361int ret;
362void *map;
363
364/* create dumb buffer */
365memset(&amp;creq, 0, sizeof(creq));
366creq.width = 1920;
367creq.height = 1080;
368creq.bpp = 32;
369ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &amp;creq);
370if (ret &lt; 0) {
371 /* buffer creation failed; see "errno" for more error codes */
372 ...
373}
374/* creq.pitch, creq.handle and creq.size are filled by this ioctl with
375 * the requested values and can be used now. */
376
377/* create framebuffer object for the dumb-buffer */
378ret = drmModeAddFB(fd, 1920, 1080, 24, 32, creq.pitch, creq.handle, &amp;fb);
379if (ret) {
380 /* frame buffer creation failed; see "errno" */
381 ...
382}
383/* the framebuffer "fb" can now used for scanout with KMS */
384
385/* prepare buffer for memory mapping */
386memset(&amp;mreq, 0, sizeof(mreq));
387mreq.handle = creq.handle;
388ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &amp;mreq);
389if (ret) {
390 /* DRM buffer preparation failed; see "errno" */
391 ...
392}
393/* mreq.offset now contains the new offset that can be used with mmap() */
394
395/* perform actual memory mapping */
396map = mmap(0, creq.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mreq.offset);
397if (map == MAP_FAILED) {
398 /* memory-mapping failed; see "errno" */
399 ...
400}
401
402/* clear the framebuffer to 0 */
403memset(map, 0, creq.size);
404</programlisting>
405
406 </refsect2>
407
408 </refsect1>
409
410 <refsect1>
411 <title>Reporting Bugs</title>
412 <para>Bugs in this manual should be reported to
Eric Engestrom10ca5e12017-04-04 18:05:53 +0100413 https://bugs.freedesktop.org/enter_bug.cgi?product=DRI&amp;component=libdrm
Eric Engestrom294be262017-04-04 17:37:02 +0100414 under the "DRI" product, component "libdrm"</para>
David Herrmannfd6b3692012-09-28 23:44:22 +0200415 </refsect1>
416
417 <refsect1>
418 <title>See Also</title>
419 <para>
420 <citerefentry><refentrytitle>drm</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
421 <citerefentry><refentrytitle>drm-kms</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
422 <citerefentry><refentrytitle>drm-prime</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
423 <citerefentry><refentrytitle>drmAvailable</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
424 <citerefentry><refentrytitle>drmOpen</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
425 <citerefentry><refentrytitle>drm-intel</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
426 <citerefentry><refentrytitle>drm-radeon</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
427 <citerefentry><refentrytitle>drm-nouveau</refentrytitle><manvolnum>7</manvolnum></citerefentry>
428 </para>
429 </refsect1>
430</refentry>